Creating a touch node for the Internet of things on Intel Edison
In this article, we will talk about how to design a sensor node based on Intel Edison. Let us build components, programming and testing. True, a stand-alone device in the age of the Internet of things is not so interesting. Therefore, after all the sensors and algorithms work, we will connect what we will have to the Web. By the way, our next material will be devoted to this. And now we offer to do iron and code.
Touch knot
The touch node consists of several sensors.
Passive infrared motion sensor
Analog temperature sensor. It can be either TMP036 or LM35. With the exception of some variable offsets, both have the same temperature characteristics at 10 mV of voltage per degree Celsius.
Photoresistor (light sensor).
Command button
The touch node also includes a pair of LEDs, they are needed for debugging purposes. ')
Red LED that turns on and off when you press a button.
Green LED that turns on when a motion sensor is triggered.
Here is a schematic diagram of the sensor node, created by means of the Fritzing application.
Schematic diagram of the device
To build a touch node, you need the following components:
1 x Edison module.
1 x Arduino Edison Expansion Board
2 x 200 ohm resistor.
2 x 1 kΩ resistor.
1 x 10 kΩ resistor.
1 x command button.
2 x LED. We used red and green, but any others would do.
1 x temperature sensor, TMP036 or LM35.
1 x infrared motion sensor.
1 x board for solderless prototyping.
Wires or jumpers for prototyping.
Similar components can be found at various suppliers that serve retail customers. For example, in Adafruit or Sparkfun . If you need large amounts of components in Mouser Electronics or DigiKey, you can try to find the same, but a bit cheaper.
Program for Arduino
A program for Arduino that implements the functionality of the sensor node is shown below. Readers familiar with the development for Arduino, will be able to easily understand this code. However, we want to clarify here some implementation features and point out several differences between Edison and ordinary Arduino (for example, Arduino Uno).
Interrupts are used to process signals from a button and a motion sensor. Since input events for these devices occur asynchronously, they are best handled using an interrupt mechanism. Interrupts in Edison do not behave the same as in Arduino Uno. The key differences are as follows:
Interrupts in Edison can generate all GPIO pins. In Arduino Uno, only pins 2 and 3 can generate interrupts. As a result, more flexible constructions can be implemented on Edison.
Since in Edison all pins can generate interrupts, in the attach_interrupt call, the pin number is used as the interrupt channel, not the predefined numbers 0 or 1, as in Arduino Uno.
In Edison, the millis () timer continues to work in the interrupt handler. This makes it possible to make calls to measure time intervals.
The motion sensor sets a high (HIGH) logical voltage level at the signal contact when motion is detected. The signal remains at this level for a few seconds and then switches to a low (LOW) logical level. In order to get the history of events recorded by the sensor, we measure the duration of the pulses corresponding to the detection of movements and accumulate them in a global counter. Every minute we measure the activity level by calculating the ratio of the amount of time in which the motion sensor gave out the HIGH value to the total duration of the observation interval (1 minute). Activity level information is displayed as a percentage. Thus, if no movements were recorded, the activity level would be zero. If the sensor recorded movements throughout the minute, the activity level will be close to 100%. The activity level is reset to zero at the beginning of the next observation interval.
In order to prevent the occurrence of false interruptions from a button arising from the bouncing of the switch contacts, we will track the time when the last interruption occurred. If the new arrives faster than 200 ms after the previous one, we consider it false and ignore.
Edison uses VCC, the positive pole of the DC source, as the reference voltage for the analog-to-digital converter (ADC). When powering the board from a USB port, the VCC voltage may not be exactly 5 V. Most likely, it will be in the range of 4.8 V to 5.1 V. You must use the real reference voltage to calculate the resolution of the ADC. In order to measure the supply voltage and calculate the resolution (VCC / 1024), a voltmeter can be used. The resulting value will be the resolution of a 10-bit Edison analog-to-digital converter.
/* Intel Edison : 1) : , 2) : 3) : 4) : Copyright (c) 2015 Intel Corporation THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <Arduino.h> // #define RED_LED 10 // #define GREEN_LED 11 // #define PIR_SENSOR 12 // #define BUTTON 13 // 10K // #define LIGHT_SENSOR A0 // #define TEMP_SENSOR A1 // TMP36 LM35 #define MIN_PULSE_SEPARATION 200 // #define ADC_STEPSIZE 4.61 // , . 4.72 VCC, #define USE_TMP036 1 #if (USE_TMP036 == 1) #define TEMP_SENSOR_OFFSET_VOLTAGE 750 #define TEMP_SENSOR_OFFSET_TEMPERATURE 25 #else // LM35 #define TEMP_SENSOR_OFFSET_VOLTAGE 0 #define TEMP_SENSOR_OFFSET_TEMPERATURE 0 #endif // unsigned long updateTime = 0; // volatile unsigned long activityMeasure; volatile unsigned long activityStart; unsigned long resetActivityCounterTime; // boolean toggleLED = 1; volatile unsigned long previousEdgeTime = 0; volatile unsigned long count = 0; /********************************************************************************************** ***********************************************************************************************/ void setup() { Serial.begin(115200); delay(3000); Serial.println("Ready"); pinMode(RED_LED, OUTPUT); pinMode(GREEN_LED, OUTPUT); pinMode(BUTTON, INPUT_PULLUP); pinMode(PIR_SENSOR, INPUT); attachInterrupt(BUTTON, buttonISR, RISING); // attachInterrupt(PIR_SENSOR, pirISR, CHANGE); // resetActivityCounterTime = millis(); // digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED,LOW); } /********************************************************************************************** ***********************************************************************************************/ void loop() { if (millis() > resetActivityCounterTime) { // 60 resetActivityCounterTime = millis() + 60000; Serial.print("ActivityLevel: ");Serial.println(100.0*activityMeasure/60000.0); activityMeasure = 0; } if (millis() > updateTime) { // 10 updateTime = millis() + 10000; Serial.print("Temperature sensor: "); Serial.println(readTemperature()); Serial.print("Light sensor: "); Serial.println(readLightSensor()); } delay(100); } /********************************************************************************************** , , HIGH , . , HIGH 3-5 , LOW. HIGH, . ***********************************************************************************************/ void pirISR() { int pirReading; unsigned long timestamp; timestamp = millis(); pirReading = digitalRead(PIR_SENSOR); if (pirReading == 1) { Serial.print(millis()); Serial.println(": PIR motion started"); // activityStart = timestamp; } else { int pulseWidth = timestamp-activityStart; activityMeasure += pulseWidth; Serial.print(millis()); Serial.println(": PIR motion ended"); Serial.print("Duration: "); Serial.print(pulseWidth); Serial.println(" ms"); Serial.print("ActivityMeasure: "); Serial.print(activityMeasure); Serial.println(" ms"); } // , digitalWrite(GREEN_LED, pirReading); } /********************************************************************************************** ***********************************************************************************************/ int readLightSensor() { return analogRead(LIGHT_SENSOR); } /********************************************************************************************** ***********************************************************************************************/ float readTemperature() { int sensorReading; float temperature; sensorReading = analogRead(TEMP_SENSOR); temperature = sensorReading * ADC_STEPSIZE; // temperature = (temperature - TEMP_SENSOR_OFFSET_VOLTAGE)/10.0 + TEMP_SENSOR_OFFSET_TEMPERATURE; temperature = temperature * 1.8 + 32.0; // return temperature; } /********************************************************************************************** ***********************************************************************************************/ void buttonISR() { // , Serial.print(millis()); Serial.println(": Button ISR"); if ((millis()-previousEdgeTime) >= MIN_PULSE_SEPARATION) { digitalWrite(RED_LED, digitalRead(RED_LED) ^ 1); count++; Serial.print("Count: "); Serial.println(count); } previousEdgeTime=millis(); }
Testing
In order to verify that the sensor node is working correctly, you need to conduct with it, at least, the following experiments.
If you wave your hand in front of the motion sensor, the green LED should turn on. After the hand is removed, it should burn for another 2-3 seconds and turn off.
If you bring your hand to the motion sensor, the green LED turns on. If, without removing the hand, to keep it in front of the sensor motionless, that is, to stop the movement, the green LED should turn off at the aforementioned interval.
Pressing the button should turn the red LED on and off.
In the debug window that displays data coming from the serial port, information from the temperature and illumination sensors should be displayed every 10 seconds. Messages about the level of activity recorded by the motion sensor should be displayed every minute.
If you cover the light sensor with your hand, this should be reflected in a decrease in the values of the indicators coming from it. If you light up this sensor, for example, with an LED flash, the value should be close to the maximum, that is, to 1023.
If you hold the top of the temperature sensor in your fingers, the system should detect a temperature increase. The temperature should gradually reach normal body temperature - about 95-98 degrees Fahrenheit.
Here is a video showing our experiments:
findings
We assembled a touch node using Intel Edison and wrote a program for it in the Arduino IDE. Sensors of this kind can be detected in home security systems. Some differences in programming for Edison and Arduino were also considered. In the following material of this series, we will connect the sensor node to the Internet in order to make it a full participant in the Internet of Things, a real IoT device. In the final project of Mosquitto, the MQTT broker , which we have already written about, will be used as a data interface for the sensor node.