View previous topic :: View next topic |
Author |
Message |
eng.mohamedtoumi
Joined: 13 Jan 2018 Posts: 23 Location: Tun
|
I2C 18F2550 Master reader from Atmega 328P Slave |
Posted: Sat Mar 17, 2018 7:43 am |
|
|
Hello I'm trying to write data via I2C
from the Atmega MCU to the 18F2550 MCU.
I need to set the 18F2550 AS A MASTER
and the Atmega 328P as a Slave.
Since Atmega works with 7-bit addressing i have managed
to set the slave address to (0x88 in the Atmega code)
and (0x10 in the 18F2550 code ).
[address in 18F code=2*address in Atmega code] ...
But still the data received on the PIC MCU is wrong.
code of ATMEGA 328P SLAVE :
Code: | #include <LiquidCrystal.h>
#include <Wire.h>
const int rs = 10, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //16*2 LCD PINS
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //16*2 LCD
long cm; //distance of Usound 1 in centimeters
long cm2; //distance of Usound 2 in centimeters
int trigf= A1; // ultrasound sensor pins connected to arduino
int echof=13 ; // ultrasound sensor pins connected to arduino
int trigl = A0; // ultrasound sensor pins connected to arduino
int echol=12 ; // ultrasound sensor pins connected to arduino
long look (int trigm , int echom) // function to calculate the distance of ultrasound
{
long cmm ;
long temps;
digitalWrite(trigm, HIGH);
delayMicroseconds(10);
digitalWrite(trigm, LOW);
pinMode(echom, INPUT);
temps = pulseIn(echom, HIGH);
cmm = temps/58;
return (cmm) ;
}
void setup() {
Wire.onReceive(receiveEvent);
Wire.begin(0x88); //ADRESS GIVEN To THE ATMEGA 328P AS SLAVE
lcd.begin(16, 2);
Serial.begin(9600);
}
void loop() {
lcd.setCursor(0, 1);
cm=look(trigf,echof); //CALCULATE FIRST DISTANCE
cm2=look(trigl,echol); //CALCULATE 2nd DISTANCE
Serial.write(cm); //DISPLAY THE 1st DIStance
}
void receiveEvent(int bytes) {
Wire.write(cm); // SEND THE distance FROM ATMEGA328p to the 18F2550 via I2C
} |
Code of 18F2550 MASTER
Code: | #include <18F2550.h>
#fuses HSPLL,PROTECT,NOLVP,NOWDT,NODEBUG,PLL1,CPUDIV1,NOMCLR
#use delay (internal=8M)
#use I2C(MASTER, SDA=PIN_B6, SCL=PIN_B7, FAST=450000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include "lcd.c"
int r;
void main(){
lcd_init(); // LCD initialisation
setup_oscillator(OSC_8MHZ);
while(true){
i2c_start();
i2c_write(0x10); //CONNECT TO SLAVE 0X10 (adress given by PCM Program of the ATMEGA 328p used as a slave
delay_ms(10) ;
i2c_start(); // I2C restart
i2c_write(0x10 + 1); // adress of slave in write mode
r = i2c_read(1); // get the distance (cm = r) form the ATMEGA 328P
i2c_stop(); //I2c Stop communication
delay_ms(1000);
printf(" %d ",r); // display the distance on Virtual terminal
}
} |
ANY Solution ?
Last edited by eng.mohamedtoumi on Sat Mar 17, 2018 8:35 am; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Sat Mar 17, 2018 8:16 am |
|
|
is this line of code..
i2c_write(0x10);
the slave address ??
if so, 0x10 != 0x88 !
it would help, me, other, and you if you add comments at the end of lines of code. While you know what you wrote and why, we don't have a clear understanding of your code.
also
what are the I2C bus pullups? what distance are the chips from each other?
I'd actually make the I2C bus SLOW NOT fast !! At least for testing purposes as it makes it easier to scope out.
and
does the PCM P's I2C scanner program see the 'slave' at address 0x88 ? That test needs to be done first to confirm both basic hardware and software.
Jay |
|
|
eng.mohamedtoumi
Joined: 13 Jan 2018 Posts: 23 Location: Tun
|
|
Posted: Sat Mar 17, 2018 8:26 am |
|
|
thank you for your response ...
1) yes the I2C communication is working correctly when i tried to send
data from the 18F2550 to Atmega And i verified that it is correct So i don't think that it is a hardware problem ...(PULLUPS 4.7k on both SDA and SCL)
2) I've used PCM P's I2C scanner program :
I've Set the Slave address to 0x88 (in the Arduino Code as mentioned)
and the PCM gave me 0x10 !!! (Arduino is on 7 bit addressing while 18F2550 on 8 bit addressing )
3)i2c_write(0x10) IS A LINE OF THE CODE it is the slave address given by the PCM P' I2C Scanner program
PS : I VE added some comments to the codes if you want to check them |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 17, 2018 10:13 am |
|
|
Arduino uses 7-bit i2c addressing, so 0x88 is not correct. 0x88 is using
8-bits. In 7-bit addressing, the top bit is not used.
So your 0x88 slave address really becomes 0x08. Then to convert it to
8-bit mode, multiply it by 2 and you get 0x10. This explains why it works.
Get rid of the 0x88 in the Arduino code. Change it to:
It will work the same way, but it won't be confusing. |
|
|
eng.mohamedtoumi
Joined: 13 Jan 2018 Posts: 23 Location: Tun
|
|
Posted: Sat Mar 17, 2018 3:06 pm |
|
|
hello I've changed it but i still same problem ... master can't read data from slave ... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sat Mar 17, 2018 3:16 pm |
|
|
You have the distance declared as a long int. int32. So the wire.write handler will be trying to write four bytes.
Your master needs to issue four reads, with only the last one having a NACK.
Currently you will only be reading the MSB of the cm distance. |
|
|
eng.mohamedtoumi
Joined: 13 Jan 2018 Posts: 23 Location: Tun
|
|
Posted: Sat Mar 17, 2018 3:39 pm |
|
|
Ttelmah wrote: | You have the distance declared as a long int. int32. |
Even when i tried to send only data of type int the code didn't work.
Atmega 328p code:
Code: | void receiveEvent(int bytes) {
Wire.write(5);
} |
and the pic code is
Code: | while(true){
i2c_start();
delay_ms(10);
i2c_write(0x10); /* Device Address */
delay_ms(10);
i2c_start(); // restart condition
delay_ms(10);
i2c_write(0x10 + 1);
delay_ms(10);
r = i2c_read(0);
delay_ms(10);
i2c_stop();
printf ("r = 0x%2.2X\r\n", r);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Mar 18, 2018 1:32 am |
|
|
Quote: | void receiveEvent(int bytes) {
Wire.write(5);
} | I think your Arduino slave code is wrong. You are using the
receiveEvent() to write. None of the Arduino examples that I looked
do this. They all use requestEvent() to write.
Look at the box on "Basic Algorithm":
http://www.berryjam.eu/2014/07/advanced-arduino-i2c-communication/
This forum is not the place to trouble-shoot your Arduino slave code.
You need to do that on an Arduino forum. Get it working with an Arduino
master. Then ask us how to use a PIC master with it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Mar 18, 2018 6:33 am |
|
|
Also an 'int' on an Arduino is a 16 bit integer. To send a single byte, requires the byte data type. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Mar 18, 2018 8:32 am |
|
|
You need to do things one step at a time.
Though Arduino code is 'off topic', I'm sure some of the other posters here will be involved in stuff that talks between the PIC and the Arduino at some point, so will post a couple of hints:
The Arduino does not receive. It is being asked to transmit.
Code: |
//rest from the existing code
byte cm; // one byte type.
void setup(void)
{
Wire.begin(0x08); //ADDRESS GIVEN To THE ATMEGA 328P AS SLAVE
Wire.onRequest(requestEvent); //On event
lcd.begin(16, 2);
Serial.begin(9600);
}
void requestEvent(void)
{ //master requests data from slave
Wire.write(cm); // one byte as PIC code expects
}
|
However I'd test your PIC master first, reading bytes from a know working hardware slave device. Only once you have this end working, switch to trying to link the two devices.
and as a further comment:
Code: |
while(true){
i2c_start();
delay_ms(10);
i2c_write(0x10); /* Device Address */
delay_ms(10);
i2c_start(); // restart condition
delay_ms(10);
i2c_write(0x10 + 1);
delay_ms(10);
r = i2c_read(0);
delay_ms(10);
i2c_stop();
printf ("r = 0x%2.2X\r\n", r);
}
|
You don't have to do the restart for the slave code as shown.
You can just directly send the read address.
The point about 'restarting' on a master, is so you can _write_ a register address, and then turn the bus round to read from this address. If you are just doing a device that returns a value always starting from the same point, there is no need for the restart. |
|
|
|