Go Down

Topic: I2C with RPi and acting as ADC. (Read 2449 times) previous topic - next topic

HeraldPoro

Hi, I'm new here and I'm not even sure is this the correct board to post at but here I go.

I use my RPi to push data from sensors to Google Sheets but however, my sensors' output are analogue.

Currently all my USB ports on the RPi are being used by other devices and I see online that I can use I2C to let the Arduino and RPi to communicate.

My first question would be, is it possible to make an Arduino into an ADC (with multiple analogue inputs) and then send said value(s) when the RPi polls for them?

My second question would be, if the first question would work, would be how?

Thanks in advance for all the help :D

Riva

My first question would be, is it possible to make an Arduino into an ADC (with multiple analogue inputs) and then send said value(s) when the RPi polls for them?
Yes

My second question would be, if the first question would work, would be how?
Google "rpi to arduino i2c slave". For me the top hits are here and here. These give the basics of what your looking to do.
Don't PM me for help as I will ignore it.

Poki

If you need fast sampling, using an ADC with SPI interface. This solution avoids the problems with connecting AVR 5V logic to Rpi 3.3V logic. But this does not involve an Arduino board so I guess it is off-topic.

HeraldPoro

Google "rpi to arduino i2c slave". For me the top hits are here and here. These give the basics of what your looking to do.
Thanks! Helped me out a lot here!

But however, I ran into a problem when I was trying to ask my Arduino to send the sensor data to my RPi.

The RPi code:
Code: [Select]
from smbus import SMBus

addr = 0x8 # bus address
bus = SMBus(1) # indicates /dev/ic2-1

def StringToBytes(val):
    retVal = []
    for c in range(val):
            retVal.append(ord(c))
    return retVal

bus.write_byte(addr, 0x1)
val = bus.read_byte_data(addr, 0x020)
byterecieve = StringToBytes(val)
print (val)


Arduino Code:
Code: [Select]
#include <Wire.h>

const int ledPin = 13; // onboard LED
static_assert(LOW == 0, "Expecting LOW to be 0");
int watercon = 0;     //water concentration

void setup() {
  Wire.begin(0x8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Wire.onRequest(sendData);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); // turn it off
  Serial.begin(9600);
}

void loop() {
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    watercon = analogRead(A0);
    Serial.println (watercon);
  }
}

void sendData(){
  Wire.write(watercon);
}
}


Apparently on the serial monitor, the readings would be 0-20 but on my RPi the values would always be 0.

Any help would be very much preferred. Thanks ^^

Riva

Python is not a language I like but hopefully the below code will work...
Code: [Select]
from smbus import SMBus

addr = 0x8 # bus address
bus = SMBus(1) # indicates /dev/ic2-1


bus.write_byte(addr, 0x00, 0x1)      # send anything to read the slave
val = bus.read_word_data(addr, 0x00) # Read 2 bytes back
print (val)


The Arduino code that should hopefully work with the above is...
Code: [Select]
#include <Wire.h>

int watercon = 0;                           // water concentration

void setup()
{
  Serial.begin(9600);
  Wire.begin(0x8);                          // join i2c bus with address #8
  Wire.onReceive(receiveEvent);             // register event
  Wire.onRequest(requestEvent);
}

void loop()
{
}

// function that executes whenever data is received from master
void receiveEvent(int howMany)
{
  watercon = analogRead(A0);                // Read analogue pin
  Serial.println (watercon);                // Print it
  while (Wire.available())                  // loop through and read all i2c data
  {
    Wire.read();                            // receive byte
  }
}

// function that executes whenever master requests data
void requestEvent()
{
  Wire.write(watercon);                     // Send lower byte of the analogue pin reading
  Wire.write(watercon >> 8);                // Send upper byte of the analogue pin reading
}


It is not elegant and could be greatly improved but hopefully it will work.
Don't PM me for help as I will ignore it.

HeraldPoro

Python is not a language I like but hopefully the below code will work...
Code: [Select]
from smbus import SMBus

addr = 0x8 # bus address
bus = SMBus(1) # indicates /dev/ic2-1


bus.write_byte(addr, 0x00, 0x1)      # send anything to read the slave
val = bus.read_word_data(addr, 0x00) # Read 2 bytes back
print (val)


The Arduino code that should hopefully work with the above is...
Code: [Select]
#include <Wire.h>

int watercon = 0;                           // water concentration

void setup()
{
  Serial.begin(9600);
  Wire.begin(0x8);                          // join i2c bus with address #8
  Wire.onReceive(receiveEvent);             // register event
  Wire.onRequest(requestEvent);
}

void loop()
{
}

// function that executes whenever data is received from master
void receiveEvent(int howMany)
{
  watercon = analogRead(A0);                // Read analogue pin
  Serial.println (watercon);                // Print it
  while (Wire.available())                  // loop through and read all i2c data
  {
    Wire.read();                            // receive byte
  }
}

// function that executes whenever master requests data
void requestEvent()
{
  Wire.write(watercon);                     // Send lower byte of the analogue pin reading
  Wire.write(watercon >> 8);                // Send upper byte of the analogue pin reading
}


It is not elegant and could be greatly improved but hopefully it will work.

Thank you super much for this!!!
It works now <3

Go Up