more notes for a bad memory - - -
Using an Arduino as an i2c Raspberry Pi slave
Inspired by Peter Mount's Blog - many thanks!
Objective
Drive fast led strip displays and use the A to D
NB!!!!!!
This is "Lesson 1 C code" (Google-copy-modify-pray-test-fix-Google again-run! - - ignore error checking)
It is saved here to back up versions that run.
They are NOT POLISHED YET - but they record progress so far
Start at the beginning
send a single byte to the Arduino and cause LED action
Arduino slave code - arduino_receive_byte.ino
#include <Wire.h> //received data //============================================================== //================================ |
Pi C code to send a byte
/* 1) send the i2c address usage :- type with spaces but without the < > */ int i2c; int rc; int main(int argc, char *argv[]) /* address is the first number after the program name */ /* the byte to send out to the arduino is the second number // i2c-0 for model B, i2c-1 for B+ and 2 rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ write(i2c,data,1) ; /* send the byte */ i2c = close(i2c); /* Sunspot (thanks to Google friends) 201115 */ |
Send 2 bytes from Pi to Arduino to create a 2 byte number
(result must be an Arduino 2 byte word (int fails - why?)- (long (4 bytes) also works)
Arduino slave code - arduino_receive_byte.ino
//Raspi_slave_2_bytes_for_word-works.ino - use with /home/pi/arduino_12c/i2c_twobytesout_pi 4 hi lo
//******************************************************************* START setup Serial.begin(9600); // open the serial port at 9600 bps: digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) // =================================================================START received data Serial.print ("data[0] - high byte = "); Serial.print ("2 bytes combined into word = ");
|
Pi C code to send 2 bytes
/* 1) send the i2c address usage :- type with spaces but without the < > */ int i2c; int rc; int main(int argc, char *argv[]) /* address is the first number after the program name */ /* the first byte to send out to the arduino is the second number /* the second byte to send out to the arduino is the second number // i2c-0 for model B, i2c-1 for B+ and 2 rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ //printf("Sending %d\n", data[0]); //usleep(500000); printf("Sending %d\n", data[0]); i2c = close(i2c); /* Sunspot (and thanks to Google friends) 211115 */ |
A discovery
The Arduino code above (Raspi_slave_2_bytes_for_word-works.ino)
also receives and combines 2 bytes from i2cset that comes with i2c tools
but the high byte cannot be bigger than 0xF9
i2cset -y 0 0x04 0xF9 0xFF b (0 is the unused register, address is 4, high byte, low byte, b means send byte)
The Arduino output is -
data[0] - high byte = 249
data[1] - low byte = 255
2 bytes combined into word = 63999
Send a command number and 2 bytes from Pi to Arduino to create a 2 byte number
and have the Arduino return a 2 byte number (up to 65535) back to the Pi
Pi C code
// /home/pi/arduino_i2c/Pi-Ard_2_bytes_both_ways.c // general purpose arduino i2c driver - send 2 bytes - first is a command // use like ./Pi-Ard_2_bytes_both_ways 4 3 255 255 (for i2c address 4 command 3) #include <string.h> // check for correct input structure // --------------------------------------------------------the arduino i2c address // ----------------------------------------------------------the command byte // use /dev/i2c-0 for Pi model B, /dev/i2c-0 for B+ and 2 combined = from_arduino1; //send data[1] to rightmost 8 bits // make Arduino derived data available for Blassic basic master programs
|
Arduino code
// Pi-Ard_2_bytes_both_ways-1 (for Pi code Pi-Ard_2_bytes_both_ways.c) #include <Wire.h> //=====================================================================setup START //--------------------------------------------------------------------loop START if (command==1) { if (command==2) { PrintOut (); if (command==3) { //________________________________________________________________ receive data START //++++++++++++++++++++++++++++++++++ data[0]=1 //_______________________________________________________________ send data to Pi START byte test[] = {highByte(send_to_Pi),lowByte(send_to_Pi)}; //============================================================ functions below this line // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FUNCTION GetTemp |
Pi ssh session
root@raspberrypi:/home/pi/arduino_i2c# gcc Pi-Ard_2_bytes_both_ways.c -o Pi-Ard_2_bytes_both_ways root@raspberrypi:/home/pi/arduino_i2c# ./Pi-Ard_2_bytes_both_ways 4 1 0 255 address = 4 command = 1 data[1] = 0 data[2] = 255 I2C: Connecting I2C: acquiring i2c address 0x4 Sending command - data[0] 1 Sending byte - data[1] 0 Sending byte - data[2] 255 from_arduino1 = 255 from_arduino2 = 255 combine arduino1 and arduino2 into 2 byte number = 65535 root@raspberrypi:/home/pi/arduino_i2c# ./Pi-Ard_2_bytes_both_ways 4 2 255 0 address = 4 command = 2 data[1] = 255 data[2] = 0 I2C: Connecting I2C: acquiring i2c address 0x4 Sending command - data[0] 2 Sending byte - data[1] 255 Sending byte - data[2] 0 from_arduino1 = 0 from_arduino2 = 26 combine arduino1 and arduino2 into 2 byte number = 26 root@raspberrypi:/home/pi/arduino_i2c# ./Pi-Ard_2_bytes_both_ways 4 3 255 255 address = 4 command = 3 data[1] = 255 data[2] = 255 I2C: Connecting I2C: acquiring i2c address 0x4 Sending command - data[0] 3 Sending byte - data[1] 255 Sending byte - data[2] 255 from_arduino1 = 0 from_arduino2 = 33 combine arduino1 and arduino2 into 2 byte number = 33 root@raspberrypi:/home/pi/arduino_i2c# |
Arduino serial monitor
command byte 1 received-LED 1 pulse, send_to_Pi is ->65535 data[0] - command byte = 1 data[1] - 2nd byte received = 0 data[2] - 3rd byte received = 255 data[1] (high byte) and data[2] (low byte) combined into 2byte arduino word = 255
command byte 2 received-LED 2 pulses, send_to_Pi (temperature) is ->26 data[0] - command byte = 2 data[1] - 2nd byte received = 255 data[2] - 3rd byte received = 0 data[1] (high byte) and data[2] (low byte) combined into 2byte arduino word = 65280
command byte 3 received-LED 3 pulses, send_to_Pi is ->33 data[0] - command byte = 3 data[1] - 2nd byte received = 255 data[2] - 3rd byte received = 255 data[1] (high byte) and data[2] (low byte) combined into 2byte arduino word = 65535 |
Now add some sensors etc to the Arduino
NB just a first try!!
A 2000 ohm linear potentiometer feeds 0 to 5 volts to pin A2
A WS2812 8 LED 3 colour bar has the data lead connected to pin D8
I see
"Sketch uses 7,808 bytes (25%) of program storage space. Maximum is 30,720 bytes"
Thanks to Adafruit
Arduino code
// Pi-Ard_2_bytes_both_ways-pot-1 (for Pi code Pi-Ard_2_bytes_both_ways.c) #include <Wire.h> #include <Adafruit_NeoPixel.h> #define SLAVE_ADDRESS 0x04 int potPin = 2; // select the input pin for the potentiometer //=====================================================================setup START strip.begin();// Initialize all the variables //--------------------------------------------------------------------loop START
// BarDisplay(potval); if (command==1) { } if (command==2) { PrintOut (); if (command==3) { //___________________________________________________________________ receive data START //++++++++++++++++++++++++++++++++++ data[0]=1 //_______________________________________________________________ send data to Pi START byte test[] = {highByte(send_to_Pi),lowByte(send_to_Pi)}; //============================================================ functions below this line // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FUNCTION GetTemp |
./Pi-Ard_2_bytes_both_ways 4 1 4 0
sends the maximum signal (1024) to the LED strip and it lights up all red
How fast will this crude code run ?
- remove all the delays and print statements
Pi code without print statements
// /home/pi/arduino_i2c/Pi-Ard_2_bytes_both_ways_save_to_ram_int_in.c // general purpose arduino i2c driver - send 2 bytes - first is a command // use like ./Pi-Ard_2_bytes_both_ways 4 1 65535 #include <string.h> // check for correct input structure // --------------------------------------------------------the arduino i2c address // ----------------------------------------------------------the command byte // printf("data[2] low byte; = %d\n", data[2]); // use /dev/i2c-0 for Pi model B, /dev/i2c-0 for B+ and 2 combined = from_arduino1; //send data[1] to rightmost 8 bits |
Arduino code without print statements
This could be much faster with better use of the NeoPixel LED code -
I am trying to determine whether the Pi should not be employed in the loop
when I display live changes in sound detected on a microphone
// Pi-Ard_2_bytes_both_ways-pot-1 (for Pi code Pi-Ard_2_bytes_both_ways.c) #include <Wire.h> #include <Adafruit_NeoPixel.h> #define SLAVE_ADDRESS 0x04 int potPin = 2; // select the input pin for the potentiometer //=====================================================================setup START strip.begin();// Initialize all the variables //--------------------------------------------------------------------loop START
// BarDisplay(potval); if (command==1) { } if (command==2) { PrintOut (); if (command==3) { //__________________________________________________________________________________ receive data START //++++++++++++++++++++++++++++++++++ data[0]=1 //_______________________________________________________________ send data to Pi START byte test[] = {highByte(send_to_Pi),lowByte(send_to_Pi)}; //============================================================ functions below this line // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FUNCTION GetTemp |
#!/usr/sbin/blassic LABEL StartAgain for i=1024 to 0 STEP -114 Arduino_C_driver$ = "/home/pi/arduino_i2c/Pi_send_int_to_ard_no_printout "+address$+" "+command$+" "+input_int$ 'PRINT " i2c address is ",address$ SHELL Arduino_C_driver$ GOTO StartAgain SYSTEM |
The 8 LEDs scan in just over 1 second
I think
the function void BarDisplay(int x) could be driven faster with cleaner code
Long term objective
Try to display the sound of bee activity via a low frequency filter to detect swarms and use the bar graph as an active sound level display.
- ESP8266 with microphone, MSGEQ7as frequency filter, swarm noise frequency channel level sampling at the bee hive
- - wifi to LAN - - Pi to send amplitude to Arduino and NeoPixel .
Perhaps?
https://deadbird.fr/?p=671
- so more to come . . . .
Please email me if you want to swap notes