|
|
View previous topic :: View next topic |
Author |
Message |
OlivierV
Joined: 25 Feb 2019 Posts: 3
|
I2C 16F1827 Master & Arduino nano Slave |
Posted: Mon Feb 25, 2019 5:28 am |
|
|
Hi everyone,
I'm trying to get i2c communication between a PIC 16F1827 and an Arduino nano to transfer some data (an int).
I have been able to get Arduino to Arduino i2c to work but not between the PIC and the Arduino.
The code I'm currently using:
Master (PIC 16F1827)
Code: |
#include <16F1827.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,MCLR,NOBROWNOUT
#use delay(clock=32000000)
#use rs232(baud=9600, xmit=PIN_A0, rcv=PIN_A1, STREAM=PC)
#use i2c(Master, sda=PIN_B1, scl=PIN_B4)
#define SLAVE1_write 0x08
#define SLAVE1_read 0x09
void main(){
int myBPM = 0;
fprintf(PC, "\r\nmyBPM= %d", myBPM);
while(1){
i2c_start();
i2c_write(SLAVE1_write);
myBPM = i2c_read(0);
i2c_stop();
fprintf(PC, "\r\nmyBPM= %d", myBPM);
delay_ms(1000);
}
}
|
Slave (Arduino Nano) - Arduino gets signal from a pulse sensor, converts it to BPM and then transmits it to the PIC
Code: |
#define USE_ARDUINO_INTERRUPTS true
#include <PulseSensorPlayground.h>
#include <Wire.h>
// Variables
const int PulseWire = 0;
int Threshold = 600;
int myBPM = 0;
PulseSensorPlayground pulseSensor;
void setup() {
Serial.begin(9600);
pulseSensor.analogInput(PulseWire);
pulseSensor.setThreshold(Threshold);
Wire.begin(8);
Wire.onRequest(requestEvent);
if (pulseSensor.begin()) {
Serial.println("We created a pulseSensor Object !");
}
}
void loop() {
myBPM = pulseSensor.getBeatsPerMinute();
if (pulseSensor.sawStartOfBeat()) {
Serial.write(myBPM);
Serial.println("♥ A HeartBeat Happened !");
Serial.print("BPM: ");
Serial.println(myBPM);
}
delay(20);
}
void requestEvent(){
Wire.write(myBPM);
}
|
When I run the system I get the following:
1. Some really strange sets of figures displayed (+x A5, etc...)
2. The first fprintf doesn't print
3. I keep getting the result "myBPM= -1" printed every second (so the while loop with delay is working)
I'm not sure what the issue is but I hope someone has tried i2c PIC master and Arduino slave before and can help me!
Extra notes:
PIC and Arduino share a ground
2x 10K Ohm Pullup resistors are used
I need to use the 16F1827 at 32Mhz to drive Neopixel LEDs
I'm using an Arduino as getting the BPM is much more streamlined then on PIC
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Feb 25, 2019 6:16 am |
|
|
On the PIC, you are selecting to write to the slave.....
Not surprising you don't read the right value back.
You can only read data from the slave read address. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9252 Location: Greensville,Ontario
|
|
Posted: Mon Feb 25, 2019 7:28 am |
|
|
I'd start with basic hardware first. What's the actual Vdds.? Are both micros 5 volt devices? Is the PIC 5 and the nano 3 volt ? Virtually everytime you try '5 and 3' , you'll run into problems... |
|
|
OlivierV
Joined: 25 Feb 2019 Posts: 3
|
|
Posted: Mon Feb 25, 2019 8:55 am |
|
|
Ttelmah wrote: | On the PIC, you are selecting to write to the slave.....
Not surprising you don't read the right value back.
You can only read data from the slave read address. |
So since I don't need to write anything to the Arduino should I take the i2c_write(SLAVE1_write) out?
And how do you specify to read from the Slave read address?
Just myBPM = i2c_read(SLAVE1_read)?
temtronic wrote: | I'd start with basic hardware first. What's the actual Vdds.? Are both micros 5 volt devices? Is the PIC 5 and the nano 3 volt ? Virtually everytime you try '5 and 3' , you'll run into problems... |
Both are 5 Volt devices as far as I'm aware (the pulse sensor is also 5 volts and i power that straight from the Arduino).
Also I took the code from another example post on the forum and altered it slightly(http://www.ccsinfo.com/forum/viewtopic.php?t=39242&start=6). The example was for between 2 PICs though.
Sorry if these are some dumb questions but I'm just starting out with PICs |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Mon Feb 25, 2019 9:09 am |
|
|
Basic I2C.
The first byte transmitted (note _transmitted_), after an I2C start, is
the device address, as a 7 bit value, with an eighth bit (as the Lsb), which
specifies the bus direction for the rest of the transfer. It is this bit that
distinguishes the read address from the write address.
So to write to I2C, the sequence is:
Code: |
Start
Send 'write' address
Then (optionally) send a register address.
Then send the data
Stop |
To read from I2C, with a specified register address, the sequence is:
Code: |
Start
send 'write' address
send register address
Restart
Send 'read' address *****
Read the data (with inverted ACK on last byte read)
Stop |
To read without a register address, the sequence is:
Code: |
Start
send 'read' address *****
Read data (with inverted ACK on last byte)
Stop |
The direction control bit actually signals which way the transceivers
are to work. Remember it is the same wire that is both sending and
receiving data. The direction _must_ be set to 'read' before trying to
read from the bus.
The points marked ***** are where the bus reversal is triggered.
So to read from a device without using register addresses, the sequence
would be:
Code: |
i2c_start();
i2c_write(SLAVE1_read);
myBPM = i2c_read(0);
i2c_stop();
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9252 Location: Greensville,Ontario
|
|
Posted: Mon Feb 25, 2019 9:37 am |
|
|
OK both are 5 volts, so that eliminates HW problems due to +5 vs +3...
Now, Ardunio code typically uses 7 bit I2C addresses vs PICs which use 8 bit addresses,so you'l need to confirm you're actually talking to the slave at the
correct addresses.
PCM P has an 'I2C scanner' program in the 'code library'. I'd copy/compile and run it. Actually I do that for every project that uses I2C. It'll confirm the I2C device is there AND what address it's at.
Also, be sure to have the correct I2C bus pullup resistors based on VDD ( 5 in your case), speed and distance. Typically 3k3, 4k7 will work.
I didn't really look at your code, prefer a one step,confirm hardware first approach.
Jay |
|
|
OlivierV
Joined: 25 Feb 2019 Posts: 3
|
|
Posted: Tue Feb 26, 2019 8:45 am |
|
|
Thanks Ttelmah! I was looking for a simple explanation like yours but I couldn't find one anywhere. I'll try to implement the code tomorrow and get back to you.
Ok temtronic, I'll try find the PCM P I2C scanner program and test it out to see if I have the right addresses. The current Arduino addresses I got by specifying them in the code (that it is how I got Arduino to Arduino I2C to work. See below) but that might the wrong way of doing it with a PIC.
How do I found out the right resistors to use? Is there an online calculator?
Also I got communication between the 2 to work with TTL RS232. Is there any benefits to get it to work using I2C instead of RS232? If there is no real benefit I might just stick with what I have. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19559
|
|
Posted: Tue Feb 26, 2019 9:48 am |
|
|
The PIC address will be twice the Arduino value.
The 'address' in I2C, is the upper 7 bits of the byte sent after the start.
On the PIC you work with the whole 'byte' as an entity. On the Arduino, just
with the upper seven bits.
The I2C documentation contains the calculations for the resistors.
Basically the smaller the resistor the more capacitance the bus can support.
However go too low, and standard drivers won't be able to pull the bus low.
Minimum for a 5V bus with 3mA drivers is about 1.7K. The maximum
value depends on the bus capacitance. At 5v, with a 2K pull up, you can
drive just on 400pF at standard rates. With 10K the maximum bus
capacitance is just 80pF. At 400KHz, this goes down to just 20pF.... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|