2017 May 25
#coding
#electronics
#comm
Now I that I have a master-slave network setup, I would like to see if I can get the two boards to send signals back and forth autonomously.
First, I extended the sensor test sketch to react via its LED and the serial monitor. I kept the serial monitor so I could debug along the way. One board is transmitting IR signals at random intervals. The other board is checking the IR receiver and when a signal is sensed, it triggers the LED on the board to illuminate for a short time period, then resumes loking. First the code for the master:
//IR transmit; send a signal at a random interval const int ledPin = 1; // ATtiny44 12 const int irPin = 2; // ATtiny44 11 const int irSensor = 3; // ATtiny44 10 long previousMillis = 0; //to calculate the interval of the blink without using a delay unsigned long currentMillis = 0; unsigned long ran = 0; int interval = 125; void setup() { pinMode(ledPin, OUTPUT); pinMode(irPin, OUTPUT); pinMode(irSensor, INPUT); } void loop() { ran = random(500, 2000); while (currentMillis - previousMillis < interval) //LED on timing { IR(); digitalWrite(ledPin, HIGH); currentMillis = millis(); } previousMillis = currentMillis; while (currentMillis - previousMillis < ran) //LED off timing { digitalWrite(ledPin, LOW); currentMillis = millis(); } previousMillis = currentMillis; //reset counter offset } void IR() //36kHz infrared transmitting { digitalWrite(irPin, HIGH); delayMicroseconds(20); digitalWrite(irPin, LOW); delayMicroseconds(7); }
And the code for the slave:
//IR receive; receive a signal and illuminate the LED for a brief time #include <SoftwareSerial.h> SoftwareSerial mySerial(0,7); // RX PA7 6, TX PA0 13 (flipped) // Using an ATTiny44 // Pin Configurations const int ledPin = 1; // PA1 12 const int irPin = 2; // PA2 11 const int irSensor = 3; // PA3 10 ADC3 int sensorValue = 0; // variable to store the value coming from the sensor int noSensorRead = 1; void setup() { pinMode(ledPin, OUTPUT); pinMode(irPin, OUTPUT); pinMode(irSensor, INPUT); mySerial.begin(19200); // I set this to 19200 and arduino monitor to 2400 mySerial.println("Hello"); } void loop() { sensorValue = digitalRead(irSensor);// read IR sensor write to variable mySerial.print("sensor "); mySerial.println(sensorValue); // send reading to serial //delay(10); if (sensorValue != noSensorRead) { // if IR sensed, pause reading and turn on LED digitalWrite(ledPin, HIGH); delay(1000); digitalWrite(ledPin, LOW); } else { delay(10); // pause between readings (not too fast for stability) } }
Next I will try to combine the two. As I customized this more, I needed to have a better understanding of what I was working with. millis() returns the number of milliseconds since the ATtiny44 board began running the current program. Unsigned long variables are extended size variables for number storage, and store 32 bits (4 bytes). Unlike standard longs unsigned longs won't store negative numbers, making their range from 0 to 4,294,967,295 (2^32 - 1). The only tricky bit in combining the two was getting my head around the millis() function, which is simple, if you take the time to find the information rather than making assumptions. In this way, functions can be run during a time interval, which probably would have been quite helpful a couple weeks ago when I was working with the phototransistor code variations.
//IR communication; receive a signal, send a signal, receive a signal, send a signal #include <SoftwareSerial.h> //SoftwareSerial mySerial(0,7); // RX PA7 6, TX PA0 13 (flipped) // Using an ATTiny44 // Pin Configurations const int ledPin = 1; // PA1 12 const int irPin = 2; // PA2 11 const int irSensor = 3; // PA3 10 ADC3 int sensorValue = 0; // variable to store the value coming from the sensor int noSensorRead = 1; unsigned long previousMillis = 0; //to calculate the interval of the blink without using a delay unsigned long currentMillis = 0; unsigned long ran = 125; int interval = 250; void setup() { pinMode(ledPin, OUTPUT); pinMode(irPin, OUTPUT); pinMode(irSensor, INPUT); //mySerial.begin(19200); // I set this to 19200 and arduino monitor to 2400 //mySerial.println("Hello"); } void loop() { ran = random(250, 2000); //generate a random interval sensorValue = digitalRead(irSensor);// read IR sensor write to variable //mySerial.print("sensor "); //mySerial.println(sensorValue); // send reading to serial if (sensorValue != noSensorRead) { // if IR sensed, pause reading and turn on LED digitalWrite(ledPin, HIGH); delay(interval); digitalWrite(ledPin, LOW); delay(ran); currentMillis = millis(); previousMillis = currentMillis; //set counter offset while (currentMillis - previousMillis < interval) { //LED on timing IR(); digitalWrite(ledPin, HIGH); currentMillis = millis(); } digitalWrite(ledPin, LOW); } else { delay(10); // pause between readings (not too fast for stability) } } void IR() //36kHz infrared transmitting { digitalWrite(irPin, HIGH); delayMicroseconds(20); digitalWrite(irPin, LOW); delayMicroseconds(7); }
The code works well until there is an interruption and one of the signals is missed. The smaller infrared LED has a narrower projection field. If attempting to communicate over longer distances, or with less precision in alignment, I recommend going with the wider LED. On the otherhand, a simple code like this is disrupted by any IR signal, such as an air conditioning remote, so narrowing the field of view on the receiver and/ or increasing the accuracy of the IR LED may be necessary in some scenarios.
At the beginning of that video, I pressed the signal and GND pins of one IR sensor together to fake a signal. That is one problem that needs to be addressed, when a signal is missed, how can it be re-established? To address this, I made the whole loop operate within a timing interval that exceeds the random max. If no signal is received, the board knows it missed one and immediately attempts to reestablish the network.
//IR communication; receive a signal, send a signal, receive a signal, send a signal #include <SoftwareSerial.h> //SoftwareSerial mySerial(0,7); // RX PA7 6, TX PA0 13 (flipped) // Using an ATTiny44 // Pin Configurations const int ledPin = 1; // PA1 12 const int irPin = 2; // PA2 11 const int irSensor = 3; // PA3 10 ADC3 int sensorValue = 0; // variable to store the value coming from the sensor int noSensorRead = 1; unsigned long previousMillis = 0; //to calculate the interval of the blink without using a delay unsigned long currentMillis = 0; unsigned long ran = 125; int interval = 250; void setup() { pinMode(ledPin, OUTPUT); pinMode(irPin, OUTPUT); pinMode(irSensor, INPUT); //mySerial.begin(19200); // I set this to 19200 and arduino monitor to 2400 //mySerial.println("Hello"); } void loop() { currentMillis = millis(); previousMillis = currentMillis; while (currentMillis - previousMillis < interval) { // Reestablishing connection IR(); digitalWrite(ledPin, HIGH); currentMillis = millis(); } digitalWrite(ledPin, LOW); previousMillis = currentMillis; //set counter offset while ( currentMillis - previousMillis < 2500) { // if the timing of this exceeds random max, reestablish sensorValue = digitalRead(irSensor); // read IR sensor write to variable //mySerial.print("sensor "); //mySerial.println(sensorValue); // send reading to serial if (sensorValue != noSensorRead) { // if IR sensed, pause reading and turn on LED digitalWrite(ledPin, HIGH); delay(interval); digitalWrite(ledPin, LOW); ran = random(250, 2000); //generate a random interval delay(ran); currentMillis = millis(); previousMillis = currentMillis; //set counter offset while (currentMillis - previousMillis < interval) { //LED on timing IR(); digitalWrite(ledPin, HIGH); currentMillis = millis(); } digitalWrite(ledPin, LOW); previousMillis = currentMillis; //set counter offset } else { delay(10); // pause between readings (not too fast for stability) currentMillis = millis(); } } } void IR() //36kHz infrared transmitting { digitalWrite(irPin, HIGH); delayMicroseconds(20); digitalWrite(irPin, LOW); delayMicroseconds(7); }
Next I tried to setup a system where one board would first confirm a message was received, then wait a random interval, and send a new message. After an hour and some change of work, my mind is spinning and I do not quite have it working yet. Here is my current sketch.
//IR communication; receive a signal, confirm, send a signal, confirm, receive a signal //#include <SoftwareSerial.h> //SoftwareSerial mySerial(0,7); // RX PA7 6, TX PA0 13 (flipped) // Using an ATTiny44 // Pin Configurations const int ledPin = 1; // PA1 12 const int irPin = 2; // PA2 11 const int irSensor = 3; // PA3 10 ADC3 int sensorValue = 0; // variable to store the value coming from the sensor unsigned long previousMillis = 0; //to calculate the interval of the blink without using a delay unsigned long currentMillis = 0; unsigned long ran = 125; int interval = 250; void setup() { pinMode(ledPin, OUTPUT); pinMode(irPin, OUTPUT); pinMode(irSensor, INPUT); //mySerial.begin(19200); // I set this to 19200 and arduino monitor to 2400 //mySerial.println("Hello"); currentMillis = millis(); //reset timing previousMillis = currentMillis; while (currentMillis - previousMillis < interval) { //startup IR(); digitalWrite(ledPin, HIGH); currentMillis = millis(); } digitalWrite(ledPin, LOW); } void loop() { sensorValue = digitalRead(irSensor); // read IR sensor write to variable //mySerial.print("sensor "); //mySerial.println(sensorValue); // send reading to serial if (sensorValue == HIGH) { // if IR sensed, respond, delay random, then send new while (sensorValue == LOW) { // wait until the entire signal was received //digitalWrite(ledPin, HIGH); delay(10); //in case of missed signals sensorValue = digitalRead(irSensor); } //digitalWrite(ledPin, LOW); //delay(10); //visual confirmation of transition from read to send currentMillis = millis(); //reset timing previousMillis = currentMillis; while (currentMillis - previousMillis < interval) { //confirm message receipt IR(); digitalWrite(ledPin, HIGH); currentMillis = millis(); } digitalWrite(ledPin, LOW); ran = random(500, 1000); //generate a random interval then delay delay(ran); while (sensorValue == HIGH) { //send message and wait for confirm currentMillis = millis(); //reset timing previousMillis = currentMillis; while (currentMillis - previousMillis < interval) { // send a message IR(); digitalWrite(ledPin, HIGH); currentMillis = millis(); } digitalWrite(ledPin, LOW); //delay(20); //give other board a chance to respond currentMillis = millis(); //reset timing previousMillis = currentMillis; while (sensorValue == HIGH && currentMillis - previousMillis < interval*1.1) { // check message receipt sensorValue = digitalRead(irSensor); } } delay(200); // time for the signal to be sent before returning to sensing } else { delay(10); // pause between readings (not too fast for stability) } } void IR() //36kHz infrared transmitting { digitalWrite(irPin, HIGH); delayMicroseconds(20); digitalWrite(irPin, LOW); delayMicroseconds(7); }
Download project files
I will post links to resources I have found helpful here.
Share this post...
« Previous post :: Processing Light Graph
Enough with the tutorials. Now I would like to start putting these together with some kind of simple visual or audio interface connected to sensor readings. I started by looking at this former Fab Academy student's work mapping phototransistor settings to a dynamically configurable 3D model. He was able to combine sensor readings from arduino with a Processing sketch from Open Processing Org, a wonderful place for sharing processing sketches. I went there with the intention to grab a sketch, however I was a little overwhelmed so instead I started looking at former Fab Academy students' pages for a sketch...
Next post :: Grow Module | The science »
The nonvascular bryophyte microbial fuel cell operates in two main zones: anode and cathode. The anode side is a layer of moss, two mixtures of cotton and carbon (10:1, cotton : carbon weight) sandwiching a single layer of stainless steel mesh (as thin as possible). This anode mixture is from the 2016 October 3 Royal Society published work of Paolo Bombelli, et al. Electrical output of bryophyte microbial fuel cell systems is sufficient to power a radio or an environmental sensor. The cathode is a sandwich of acrylic (bread), rubber (condiment), hydrogen electrode (10 wt % Pt/C + 5% Nafion...