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?
HeraldPoro:
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.
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.
Riva:
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:
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:
#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.
Python is not a language I like but hopefully the below code will work…
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…
#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.
Riva:
Python is not a language I like but hopefully the below code will work…
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...
#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.