Send data both ways between a Linux Sweex router and an Arduino via 12c

It
is convenient to use an Arduino to drive a graphic display and for it to display data received from my existing network of Linux router boxes.

The Arduino can also act as an analog and digital remote sensor for the Linux box.

The display below is a bright and clear TFT full colour display with 128x190 pixels (eBay under £4) and is driven by an Arduino Nano.

The Arduino is set up as an i2c slave.

The i2c master is my Sweex router (menu item 3 here) that pulls in data from my i2c and ethernet home network.

display

First working code for the Arduino - NB!!! - this is WORK IN PROGRESS!!!

// Wire Slave Receiver -------------------------------slave_receive_i2c_display2.ino
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this

// Created 29 March 2006

// This example code is in the public domain.
// ./LtoASendFiles 4 /var/www/ramdisk/chicken_feed_percent.dat

 

#define cs 10 // Arduino-Pin an Display CS
#define dc 9 // Arduino-Pin an
#define rst 8 // Arduino Reset-Pin
#include <Adafruit_GFX.h> // Adafruit Grafik-Bibliothek
#include <Adafruit_ST7735.h> // Adafruit ST7735-Bibliothek
#include <SPI.h>
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); // Display-Bibliothek Setup

#include <Wire.h>

String StringFromSweex = String("");

void setup()
{

// send an intro:
Serial.println("\n\nAppending to a string:");
Serial.println();



tft.initR(INITR_BLACKTAB); // ST7735-Chip initialisieren
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
Wire.onRequest(requestEvent); // register event
Serial.begin(9600); // start serial for output
Serial.println("Boot Ok");
}

void loop()
{ delay(100); }

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
char c = NULL;
StringFromSweex = String("");
while(Wire.available()) // loop through all
{
c = Wire.read(); // receive byte as a character
// Serial.print(c); // print the character
StringFromSweex += c;
}
Serial.println();
Serial.println(StringFromSweex); // prints c value
Serial.println("===");

tft.fillScreen(ST7735_BLACK);
//delay(500);
tft.setTextSize(2);
tft.setTextWrap(true);
tft.setCursor(0,4);
tft.setTextColor(ST7735_YELLOW);
tft.print(StringFromSweex);

}

void requestEvent()
{
Serial.println("read");
Wire.write("Hello world from Arduino");
}

Code for the Sweex Linux router
this reads data from the Arduino and also reads data from a text file in the Linux box
and sends the data to the Arduino for it to put in the display

/* LtoASendFiles8.c

for Sweex Linux router - send the contents of a stored text file to the Arduino
and receive data from the Arduino

e.g. send the contents of /var/www/ramdisk/chicken_feed_percent.dat to the Arduino
for a fancy display that the Sweex cannot run by itself

To the program name we add
space
the i2c address as decimal
space
the name of the data file (with path)

usage e.g. - type with spaces but without the < >
<name-of-this-program> <i2c address> </var/www/ramdisk/chicken_feed_percent.dat>
*/

#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <linux/i2c.h>

int main(int argc, char** argv)
{
int i2c_file;
char filename[40];
int addr; //the i2c address comes in as the char argv[1] - we will use atoi to make it an integer
char buf[50] = {0};
size_t current_size = 0; //used to start adding chars into buf from the first place (why size_t??!!)
char buf_for_data_received[32] = {0};
int i;
int x;
char y; //use to turn x into a char

// see if he has added arguments after the program name as required===================
if ( argc != 3 ) // argc should be 3 for 2 items (i2c_address and data_filename)
// following the program name which is the first item
{
/* argv[0] (below) is this program's name - tell user how to format the command*/
printf( "usage: %s i2c_address data_filename\n", argv[0] );
}
else
{ //do everything

addr = atoi(argv[1]); /* address is the first number after the program name */

// get the i2c bus ready============================================================
sprintf(filename,"/dev/i2c/0"); //modified for Sweex router (not i2c-0)
if ((i2c_file = open(filename,O_RDWR)) < 0) {
printf("Failed to open the bus.");
exit(1);
}
if (ioctl(i2c_file,I2C_SLAVE,addr) < 0) {
printf("Failed to acquire bus access and/or talk to slave.\n");
exit(1);
}
// i2c bus now ready===============================================================

 

// now read data from the Arduino to print on the Linux box terminal ==============
// set the number of bytes we will read
// from the Arduino when the program is run
i = 24;
// the Arduino has just i characters to send to the Linux box
// (in the test it is "Hello world from Arduino")

// read the I2C data from the Arduino
if (read(i2c_file,buf_for_data_received,i) != i) {
// read(i2c_file,buf_for_data_received,i) should load i characters into buf_for_data_received[32]
// and (I guess) return a value of i
printf("Failed to read from the i2c bus.\n");
} else {
// %s below will print out the i characters in buf_for_data_received in the Linux terminal
printf("Read %d bytes from I2C:-\n%s\n",i,buf_for_data_received);
}
// end of data read from Arduino===================================================

 

// open up the Linux box stored data file and pull in the data -

// We assume argv[2] is the name of the Linux stored data filename to open
FILE *file = fopen( argv[2], "r" );

// fopen returns 0, the NULL pointer, on failure
if ( file == 0 )
{
printf( "Could not open file\n" );
}
else
{
// read one character at a time from file, stopping at EOF

while ( ( x = fgetc( file ) ) != EOF )
{
// printf( "x = %c\n", x );//if the file contains 81 - first 8, then 1, prints to the telnet Linux monitor
y = (char)x; // turn the integer x into a character y
// if x has value decimal 65 we put an A into the buf ready for sending out on i2c below
buf[current_size++] = y; // as we go round this loop buf gets more characters until we read EOF above
}
fclose( file );
}

// print out the buf contents in the terminal
// printf("buf = %s\n",buf);

// now send the string of characters in buf out on the i2c bus
i = strlen(buf);
if (write(i2c_file,buf,i) != i) {
printf("Failed to write to the i2c bus.\n");
} else {
printf("Sent %d bytes to I2C:-\n%s\n",i,buf);
}
}

i2c_file = close(i2c_file);// (some examples do not bother to do this)
}

/*

 

the Linux box data file can have a mix of letters and numbers and return characters
e.g.
123 hello
here
is some
data and text

 

Sunspot 270114

*/

The text file contains

123456789
from graham

The Linux terminal shows

midge03# ./LtoASendFiles8 4 data.txt
Read 24 bytes from I2C:-
Hello world from Arduino
Sent 22 bytes to I2C:-
123456789
from graham

The Arduino rs232 terminal shows

read

 

123456789
from graham

===

With thanks to

http://arduino.cc/en/Tutorial/MasterWriter

http://www.larsen-b.com/Article/398.html

http://blog.simtronyx.de/en/a-1-8-inch-tft-color-display-hy-1-8-spi-and-an-arduino/

with thanks!

circuit
i2c connections :-
pin A5 connects to SCL (clock)
pin A4 connects to SDA (data)

SUNSPOT HOME