14. Networking and communications¶
Assignment¶
-
Group assignment
send a message between two projects -
Individual assignment
design, build, and connect wired or wireless node(s) with network or bus addresses
Group Assignment¶
Planning¶
I will use five light sensors for my final project, and I created one board at week#11. So this week I planned to design other boards to be connected to the week#11 board, and networked them using asynchronous serial communication.
week#11 light sensor board
Network plan
Parts List for one board
parts | description | number |
---|---|---|
micro controller | ATTiny 44 | 1 |
Light sensor | PT15-21C/TR8 | 1 |
capacitor | 1uF | 1 |
resistor | 10KΩ | 2 |
resistor | 0KΩ | 2 |
header | 6pin for ISP | 1 |
header | 4pin for serial | 1 |
Design¶
I designed the board using Eagle. The difference from the week#11 design is:
- Removed FTDI header
- Relocate capacitor
Schematic
Board
Mods I created path files for SRM-20 using mods as usual.
Checked the route with visual inspection.
Milling¶
I milled the board with SRM-20.
At the 1st trial, I found that the edge of the routes were jagged.(left image)
Second trial was fine as follows(right image).
The lab instructor advised me that the probable cause was the unevenness of the sacrifice board.
Soldered all parts and connected the boards with 4 lines ( TX/RX/VCC/GND),
Networking with two boards¶
First I tried network communication with two sensor boards. The flow of the program is as follows.
- Processing application sends add(1) to board#1. ( board#1 address = 1)
- Board#1 receives the add(1), then sends the light data to Processing
- Processing application sends add(2) to board#2 ( board#2 address = 2)
- Board#2 receives the add(2), then sends the light data to Processing
- Processing app display the light data of both boards
The point of the c program is, after received the address, set port direction for output.
get_char(&serial_pins, serial_pin_in, &chr); if(chr == nodeAdd){ output(serial_direction, serial_pin_out);
After sending the light data, return the port direction for input.
put_char(&serial_port, serial_pin_out, chr); input(serial_direction, serial_pin_out);
Light Sensor graph of two boards @ Processing
Video
Networking with five boards¶
I confirmed that the week#14 boards work fine. So I duplicated three more boards and tried networking between five boards.
Light Sensor graph of five boards @ Processing
Video
C code for board 1¶
The c code below is for board#1, and the code of other boards are almost same as this code. Only difference is the definition of node address as follows.
- Board1: #define nodeAdd ‘1’
- Board2: #define nodeAdd ‘2’
- Board3: #define nodeAdd ‘3’
- Board4: #define nodeAdd ‘4’
- Board5: #define nodeAdd ‘5’
//====================================================== // light.44_nw.c //====================================================== #include <avr/io.h> #include <util/delay.h> #include <avr/pgmspace.h> #define output(directions,pin) (directions |= pin) // set port direction for output #define input(directions,pin) (directions &= (~pin)) // set port direction for input #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define pin_test(pins,pin) (pins & pin) // test for port pin #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define bit_delay_time 102 // bit delay for 9600 with overhead #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay #define char_delay() _delay_ms(10) // char delay #define serial_port PORTB #define serial_direction DDRB #define serial_pins PINB #define serial_pin_out (1 << PB0) //week11 #define serial_pin_in (1 << PB1) #define max_buffer 25 #define nodeAdd '1' void put_char(volatile unsigned char *port, unsigned char pin, char txchar) { // // send character in txchar on port pin // assumes line driver (inverts bits) // // start bit // clear(*port,pin); bit_delay(); // // unrolled loop to write data bits // if bit_test(txchar,0) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,1) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,2) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,3) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,4) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,5) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,6) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,7) set(*port,pin); else clear(*port,pin); bit_delay(); // // stop bit // set(*port,pin); bit_delay(); // // char delay // bit_delay(); } #define max_buffer 25 void get_char(volatile unsigned char *pins, unsigned char pin, char *rxbyte) { // // read character into rxbyte on pins pin // assumes line driver (inverts bits) // *rxbyte = 0; while (pin_test(*pins,pin)) // // wait for start bit // ; // // delay to middle of first data bit // half_bit_delay(); bit_delay(); // // unrolled loop to read data bits // if pin_test(*pins,pin) *rxbyte |= (1 << 0); else *rxbyte |= (0 << 0); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 1); else *rxbyte |= (0 << 1); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 2); else *rxbyte |= (0 << 2); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 3); else *rxbyte |= (0 << 3); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 4); else *rxbyte |= (0 << 4); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 5); else *rxbyte |= (0 << 5); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 6); else *rxbyte |= (0 << 6); bit_delay(); if pin_test(*pins,pin) *rxbyte |= (1 << 7); else *rxbyte |= (0 << 7); // // wait for stop bit // bit_delay(); half_bit_delay(); } int main(void) { // // main // static char chr; // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // initialize output pins // set(serial_port, serial_pin_out); input(serial_direction, serial_pin_out); //output(serial_direction, serial_pin_out); // // init A/D // // ADMUX = (0 << REFS2) | (0 << REFS1) | (0 << REFS0) // Vcc ref ADMUX = (0 << REFS1) | (0 << REFS0) // Vcc ref week11 // | (0 << ADLAR) // right adjust // | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0); // ADC3 | (0 << MUX5) | (0 << MUX4) | (0 << MUX3) | (0 << MUX2) | (0 << MUX1) | (0 << MUX0); // ADC0 week11 ADCSRB = (0 << ADLAR); // right adjust week11 ADCSRA = (1 << ADEN) // enable | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128 // // main loop // while (1) { // // send framing // get_char(&serial_pins, serial_pin_in, &chr); if(chr == nodeAdd){ output(serial_direction, serial_pin_out); /* put_char(&serial_port, serial_pin_out, 1); // put_char(&serial_port, serial_pin_out, nodeAdd); char_delay(); put_char(&serial_port, serial_pin_out, 2); char_delay(); put_char(&serial_port, serial_pin_out, 3); char_delay(); put_char(&serial_port, serial_pin_out, 4); char_delay(); */ // // initiate conversion // ADCSRA |= (1 << ADSC); // // wait for completion // while (ADCSRA & (1 << ADSC)) ; // // send result // chr = ADCL; put_char(&serial_port, serial_pin_out, chr); char_delay(); chr = ADCH; put_char(&serial_port, serial_pin_out, chr); input(serial_direction, serial_pin_out); } } }
Processing code ( Network between 2 boad )¶
/**************************************************************************** Week14 networking *****************************************************************************/ import processing.serial.*; Serial myPort; // Create object from Serial class int val; // Data received from the serial port int cnt= 0; int ltL=0; int ltH=0; int ltDat=0; int xx=0; int node = 0; int dspMode=0; int node0Id='1'; int node1Id='2'; //int node2Id='2'; //int node3Id='3'; //int node4Id='4'; boolean reqDat=false; float eps = 0.5; float filter0 = 0.0; float filter1 = 0.0; void setup() { size(550,700); myPort = new Serial(this, "/dev/cu.usbserial-A90808PQ", 9600); background(255); // Set background to white } void draw() { sendAdd(); noStroke(); fill(255, 255, 255); rect(0, 0,500, 50); rect(0, 320,500, 70); rect(0, 100,500, 20); rect(0, 450,500, 20); fill(0, 130, 130); textSize(16); text("Light Sensor Board1 (Node add = 1 )", 50,25); text("real time data = " + filter0, 50,42); text("Timeline", 50,119); text("Light Sensor Board2 (Node add = 2 )", 50,370); text("real time data = " + filter1, 50,387); // text( filter1, 400,380); text("Timeline", 50,468); float x1= map ( filter0, 0, 1024, 0, 450); fill(172, 255, 255); rect(50, 50, 450, 50); fill(0, 130, 130); rect(50, 50, x1, 50); float x2 = map ( filter0, 0, 1024, 0, 200); fill(0,130,130); rect(50+xx, 120, 1, 200); fill(172, 255, 255); rect(50+xx, 120, 1, 200-x2); float x3= map ( filter1, 0, 1024, 0, 450); fill(172, 255, 255); rect(50, 400, 450, 50); fill(242, 171, 237); rect(50, 400, x3, 50); float x4 = map ( filter1, 0, 1024, 0, 200); fill(242,171,237); rect(50+xx, 470, 1, 200); fill(172, 255, 255); rect(50+xx, 470, 1, 200-x4); if(xx++ == 450){xx=0;}; // } } void serialEvent(Serial myPort) { readLight(); println ("Serial read "); } void readLight(){ val = myPort.read(); // read it and store it in val // println(val); // println ("cnt = " + cnt); switch(cnt){ /* case 0: if(val==1){ cnt = 1;} break; case 1: if(val==2){ cnt = 2; }else if(val!=1) { cnt=0; } break; case 2: if(val==3){ cnt = 3; }else{ cnt=0; } break; case 3: if(val==4){ cnt = 4; }else{ cnt=0; } break; case 4: ltL = val; cnt = 5; break; case 5: ltH = val; ltDat = 256*ltH + ltL; if(node == 0){ filter0 = (1-eps)*filter0 + eps*ltDat; println ("filter = " + filter0); }else if(node == 1){ filter1 = (1-eps)*filter1 + eps*ltDat; println ("filter1 = " + filter1); } */ case 0: ltL = val; cnt = 1; break; case 1: ltH = val; ltDat = 256*ltH + ltL; if(node == 0){ filter0 = (1-eps)*filter0 + eps*ltDat; println ("filter = " + filter0); }else if(node == 1){ filter1 = (1-eps)*filter1 + eps*ltDat; println ("filter1 = " + filter1); } cnt = 0; reqDat=false; node++; node=node%2; // break; // } // float x1= map ( filter, 0, 1024, 0, 450); // float x1= map ( filter, 0, 1024, 0, 450); /* noStroke(); fill(0, 130, 130); text("Light Sensor ", 50,25); fill(172, 255, 255); rect(50, 50, 450, 50); fill(0, 130, 130); rect(50, 50, x1, 50); float x2 = map ( filter, 0, 1024, 0, 100); fill(0,130,130); rect(50+xx, 120, 1, 200); fill(172, 255, 255); rect(50+xx, 120, 1, 200-x2); if(xx++ == 400){xx=0;}; */ break; } } void sendAdd(){ if(!reqDat){ switch(node){ case 0: myPort.write(node0Id); break; case 1: myPort.write(node1Id); break; /* case 2: myPort.write(node2Id); break; case 3: myPort.write(node3Id); break; case 4: myPort.write(node4Id); break; */ } reqDat=true; } } /*void keyPressed() { if (key == 'A' || key == 'a'){ // コード化されているキーが押された println ("A is pressed"); myPort.write('1'); node=0; } else if (key == 'S' || key == 's'){ println ("S is pressed"); myPort.write('2'); node=1; } } */
Processing code ( Network between 5 board )¶
/**************************************************************************** Week14 Light Sensor Networking between 5 boards *****************************************************************************/ import processing.serial.*; Serial myPort; // Create object from Serial class int val; // Data received from the serial port int cnt= 0; int ltL=0; // sensor data int ltH=0; // sensor data int ltDat=0; // sensor data int node = 0; int node0Id='1'; // sensor board#1 address int node1Id='2'; // sensor board#2 address int node2Id='3'; // sensor board#3 address int node3Id='4'; // sensor board#4 address int node4Id='5'; // sensor board#5 address boolean reqDat=false; float eps = 0.5; //float filter0 = 0.0; //float filter1 = 0.0; float[] filter = {0,0,0,0,0}; //graoh int xx=0; int txSize=16; int intY = 50; int intX = 50; int spGraph = 150; int maxX = 450; int mgn=2; void setup() { size(550,810); myPort = new Serial(this, "/dev/cu.usbserial-A90808PQ", 9600); background(255); // Set background to white } void draw() { sendAdd(); // send address to board noStroke(); // display sensor graph dspGraph( 1, intY); dspGraph( 2, intY+spGraph); dspGraph( 3, intY+spGraph*2); dspGraph( 4, intY+spGraph*3); dspGraph( 5, intY+spGraph*4); if(xx++ == maxX){xx=0;}; } void serialEvent(Serial myPort) { readLight(); } void readLight(){ val = myPort.read(); // read it and store it in val switch(cnt){ case 0: ltL = val; cnt = 1; break; case 1: ltH = val; ltDat = 256*ltH + ltL; filter[node] = (1-eps)*filter[node] + eps*ltDat; cnt = 0; reqDat=false; node++; node=node%5; break; } } void sendAdd(){ if(!reqDat){ switch(node){ case 0: myPort.write(node0Id); println ("write node0"); break; case 1: myPort.write(node1Id); println ("write node1"); break; case 2: myPort.write(node2Id); println ("write node2"); break; case 3: myPort.write(node3Id); println ("write node3"); break; case 4: myPort.write(node4Id); println ("write node4"); break; } reqDat=true; } } void dspGraph(int n, int add){ fill(255, 255, 255); // clear rect(0, add-txSize,500, txSize*2+mgn); rect(0, add+txSize+mgn*3+15,500, txSize); fill(0, 130, 130); textSize(txSize); text("Light Sensor Board" + n + "(Node add = " + n + " )", intX,add); text("real time data = " + filter[n-1], intX,add+txSize+mgn); // text("Timeline", intX, add+txSize*2+mgn*3+15); float x1= map ( filter[n-1], 0, 1024, 0, maxX); fill(172, 255, 255); rect(intX, add+txSize+mgn*2, maxX, 15); fill(0, 130, 130); rect(intX,add+txSize+mgn*2 , x1, 15); fill(255,130,130); if (xx == maxX){ rect(intX+1, add+txSize*2+mgn*4+15, 1, 50); }else{ rect(intX+xx+1, add+txSize*2+mgn*4+15, 1, 50); } float x3 = map ( filter[n-1], 0, 1024, 0, 50); fill(0,130,130); rect(intX+xx, add+txSize*2+mgn*4+15, 1, 50); fill(172, 255, 255); rect(intX+xx, add+txSize*2+mgn*4+15, 1, 50-x3); }