more notes for a bad memory - - -
Using an Arduino Mega with colour LCD (UTFT) display as an i2c Raspberry Pi slave
Objective
Use an Arduino Mega to drive an LCD display as the i2c slave of a Raspberry Pi i2c master.
Display temperatures from three thermistors attached to an Arduino Nano also as i2c slave to the same Raspberry Pi
ALSO SEE THIS
This display is from Banggood
It runs the code from here but is not supported by the author of the UTFT library
(but make him a donation anyway!)
It is cheap bright and colourful and seems to have all it's pixels working.
This is a backup of my first working demonstrator - the first code to (at last!) do most of what I wanted
- (C code string handling is impossible to understand or remember if you only code twice a year! - Blassic rules!)
NB!!!!!!
This is "Lesson 1 C code" (Google-copy-modify-pray-test-fix-Google - run?)
It is saved here to back up my versions that run even if not finished - better versions may replace these at random times.
The system
A Raspberry Pi Zero is in charge of an i2c bus.
An Arduino Nano hosts 3 thermisters on analog lines 0, 1 and 2 and acts as an i2c slave at address 4.
An Arduino Mega with the LCD above
acts as an i2c slave at address 5.
The Pi runs a Blassic basic "glue script" that first calls the C code program -
pi_drive_arduino__3_Thermisters1.bas
This talks to for-Pi-from-Nano_6_bytes_for_3_thermisters.ino
The Pi saves bytes from the Nano in it's ramdisk (to save the flash memory)
The Blassic script reads from ramdisk and sends the bytes on to the Mega
by running the C code -
Pi-Ard_send_7_bytes_to_MegaLCD_get_4-a.c
Arduino Nano code (i2c slave) - send thermistor data to Raspberry Pi
(the NeoPixel code and potentiometer reading code is not used in this example)
for-Pi-from-Nano_6_bytes_for_3_thermisters
// for-Pi-from-Nano_6_bytes_for_3_thermisters (for Pi code - Pi-Ard_send_3_bytes_get_6_from_Nano) #include <Wire.h> #include <Adafruit_NeoPixel.h> #define SLAVE_ADDRESS 0x04 uint8_t templow; #define ThermistorPIN0 0 //=====================================================================setup START strip.begin();// Initialize all the variables pinMode(13, OUTPUT); //to flash the on board LED // initialize i2c as slave //--------------------------------------------------------------------------------------------------------------loop START potval = analogRead(potPin); // read the value from the potentiometer BarDisplay(combined); PrintOut (); temp=Thermistor(analogRead(ThermistorPIN0)); // read ADC and convert it to Celsius temp=Thermistor(analogRead(ThermistorPIN1)); // read ADC and convert it to Celsius temp=Thermistor(analogRead(ThermistorPIN2)); // read ADC and convert it to Celsius } //__________________________________________________________________________________________ receive data START - not needed for thermistor test //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ data[0]=1 // create the 2 byte word - there is time to do this here rather than many times in the loop //___________________________________________________________________________________________ send data to Pi START byte test[] = {highByte(send_to_Pi0),lowByte(send_to_Pi0),highByte(send_to_Pi1),lowByte(send_to_Pi1),highByte(send_to_Pi2),lowByte(send_to_Pi2)}; Wire.write(test,6); //======================================================================================================= functions below this line // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FUNCTION Get Arduino temperature delay (1000); // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FUNCTION Flash_LED_13 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FUNCTION DRIVE NeoPixel LED Strip // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>FUNCTION thermistor calculation function float Thermistor(int RawADC) { |
Raspberry Pi code (i2c master) - grab thermistor data from Nano (i2c address 4) and save to Raspberry Pi ramdisk
Pi-Ard_send_3_bytes_get_6_from_Nano.c
// /home/graham/UTFT_display/Pi-Ard_send_3_bytes_get_6_from_Nano.c // general purpose arduino i2c driver - send 2 bytes - first is a command // use like /home/graham/Pi-Ard_send_3_bytes_get_6_from_Nano 4 3 255 255 (for i2c address 4 command 3) #include <string.h> int i2c; int main(int argc, char *argv[]) // check for correct input structure // --------------------------------------------------------the arduino i2c address // ----------------------------------------------------------the command byte // ----------------------------------------------------------the two data bytes <- not needed on the Nano yet /* the forth byte to send out to the arduino is the forth number printf("I2C: Connecting\n"); // use /dev/i2c-0 for Pi model B, /dev/i2c-0 for B+ and 2 printf("I2C: acquiring i2c address 0x%x\n", address); rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ unsigned char cmd[16]; printf("Sending command - data[0] %d\n", data[0]); write(i2c, data, 3); //-------------------------------------------------------------------------------READ char buf[6]; combined1 = from_arduino0; combined2 = from_arduino2; combined3 = from_arduino4; printf("combine arduino0 and arduino1 into 2 byte number = %d\n", combined1); // make Arduino derived data available for Blassic basic master programs //save to ramdisk f = fopen("/var/www/ramdisk/from_arduino2.dat","w"); f = fopen("/var/www/ramdisk/from_arduino3.dat","w"); f = fopen("/var/www/ramdisk/from_arduino4.dat","w"); f = fopen("/var/www/ramdisk/from_arduino5.dat","w"); //save 2BytesCombined1 to ramdisk //save 2BytesCombined2 to ramdisk //save 2BytesCombined3 to ramdisk // Now wait else you could crash the arduino by sending requests too fast (not tested) close(i2c); |
Raspberry Pi code (i2c master) - send the stored thermistor data to the Arduino Mega (i2c address 5)
Pi-Ard_send_7_bytes_to_MegaLCD_get_4-a.c
// /home/graham/UTFT_display/Pi-Ard_send_7_bytes_to_MegaLCD_get_4-a.c // general purpose arduino i2c driver - send 7 bytes - first is a command then 3 pairs to build 2 2-byte numbers // use like /home/graham/UTFT_display/Pi-Ard_send_7_bytes_to_MegaLCD_get_4-a 5 1 123 0 234 0 222 0 (for i2c address 4 - command 2 - then 6 bytes for 3 2-byte numbers) #include <string.h> int i2c; int main(int argc, char *argv[]) // check for correct input structure // --------------------------------------------------------the arduino i2c address // ----------------------------------------------------------the command byte // ----------------------------------------------------------the six data bytes data[2] = atoi(argv[4]); data[3] = atoi(argv[5]); data[4] = atoi(argv[6]); data[5] = atoi(argv[7]); data[6] = atoi(argv[8]); printf("I2C: Connecting\n"); // use /dev/i2c-0 for Pi model B, /dev/i2c-1 for B+ and 2 printf("I2C: acquiring i2c address 0x%x\n", address); rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ write(i2c, data, 7); //send 7 bytes on the i2c bus // As we are not talking to direct hardware but a micro controller we /* ----------------------------------- nothing to receive from the mega lcd display - use later? combined1 = from_arduino0; //send data[1] to right most 8 bits combined2 = from_arduino2; //send data[1] to right most 8 bits printf("combine1 - arduino0 and arduino1 into 2 byte number = %d\n", combined1); // make Arduino derived data available for Blassic basic master programs //save from_arduino2 to ramdisk f = fopen("/var/www/ramdisk/from_arduino2.dat","w"); //save from_arduino2 to ramdisk //save 2BytesCombined1 to ramdisk //save 2BytesCombined2 to ramdisk close(i2c); |
Arduino Mega code (i2c slave)
- receive data from Pi and show on attached UTFT TFT liquid crystal display
MegSlaveLcd-3Thermisters-1 - - - - - EDIT 15/1/16
// MegSlaveLcd-3Thermisters-1 - - - - WORKS! 15/1/16 // Pi first argument defines the i2c address of this Arduino - - - created 11/1/16 #include <Wire.h> #include <UTFT.h> int number = 0; //=====================================================================setup START myGLCD.InitLCD(); // initialize i2c as slave //---------------------------------------------------------------------------------loop START Flash_LED_13(); //show we are alive //----------------------------------------------------------------------------drive the LCD myGLCD.fillCircle(20,20,15); myGLCD.setColor(255, 126, 120); myGLCD.setColor(0, 255, 0); myGLCD.setColor(190, 190, 255); if (command==2) {
//______________________________________________________________________________________________ receive data START
// what is the command byte? //++++++++++++++++++++++++++++++++++ data[0]=3 combined1 = word(data[2],data[1]); //high-data[2] and low-data[1] bytes combine here combined3 = word(data[6],data[5]); //_________________________________________________________ send data to Pi START - not needed for Mega display yet //=============================================================== functions below this line // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FUNCTION Flash_LED_13 |
Blassic glue script
pi_drive_arduino__3_Thermisters1.bas
#!/usr/sbin/blassic ' /home/graham/UTFT_display/pi_drive_arduino__3_Thermisters1.bas 'data 2 and 4 and 6 are high bytes 'address 4 for 3 thermisters on Nano LABEL StartAgain thermister_C_driver$ = "/home/graham/UTFT_display/Pi-Ard_send_3_bytes_get_6_from_Nano 4 3 255 255" PAUSE 4000 OPEN "/var/www/ramdisk/from_arduino0.dat" FOR INPUT AS #1:INPUT #1,arduino_byte_0$:CLOSE #1 PRINT "arduino_byte_0$ for screen = ",arduino_byte_0$ screen_C_driver$ = "/home/graham/UTFT_display/Pi-Ard_send_7_bytes_to_MegaLCD_get_4-a 5 1 " + arduino_byte_1$ + " " + arduino_byte_0$+ " " + arduino_byte_3$+ " " + arduino_byte_2$+ " " + arduino_byte_5$+ " " + arduino_byte_4$ GOTO StartAgain SYSTEM |
The display looks a bit like -
. . . . . . garden = 19.0
|
Plus a flashing circle (topleft) to show it is alive
This is my first test with thermisters. (eBay low cost 10k ohm types)
A small series potentiometer in series with the pad resistor lets you tweak the value (total resistance close to 10 k ohm)
My 3 thermisters then all read the same to 0.1 degrees C
when tied together.
(Used for greenhouse, hot-box and outdoor temperature reporting to the house)
They seem to work well on long lines (I use screened cable with 100nf capacitor across the line input)
Many thanks to all who publish open source code now woven into my code above!
The thermistor code from here gives good results at 20 degrees C
- but with all 3 probes in ice water I get 1.6 degrees
- Quick fix - add lines like -
temperature1 = temperature1 - (20 - temperature1) * 1.6/20;
(it is important to report freezing point accurately in a greenhouse)
. . . . .or go to LM75 i2c chips? . . . . .
Please email me if you want to swap notes