This tutorial explains how to make your own fire detection security system with a Pyboard, a flame sensor and an ADC convertor.
- The Pyboard and the training daughter board from HyperPanel Lab.
- An installation of a HyperpanelOS release already installed on a Linux PC, including tools for flashing and debugging. You need at least two USB ports on the computer (one for flashing and running, one for terminal).
- The Olimex ARM-USB-OCD interface & cables.
- A Ben-Gi Mini ADS1115 Module 4 channels 16 bits I2C ADC.
- Flame Sensor V2 from DFRobot available at wiki.dfrobot.com and also available in LattePanda Starter Sensor at www.lattepanda.com
.
hypv9wr64 or higher.
Flame sensor :
- We use the Flame sensor SKU DFR0076 from dfrobot. The flame sensor can be used to detect fire or other wavelength at 760 nm ~ 1100 nm light. According to datasheet, this flame sensor probe angle of 60 degrees.
Supply Voltage : 3.3V to 5V
Detection range : 20cm (4.8V) ~ 100cm (1V)
Rang of Spectral Bandwidth : 760nm to 1100nm
- In this tutorial, we have some 5V free power pins available on the daughter board so we use one of them.
- The flame sensor’s operating temperature is -25 degrees Celsius to 85 degrees Celsius, in the course of the flame it should be noted that the probe distance from the flame should not be too close in order to avoid damage.
- There is no really specification about bandwidth signal (fire) and resulting analog value. So we act that “lower value” means “no fire” and “high value” means “fire”. Detection range is 1V at 100cm so we set the ADC amplifier to this kind of range (cf. following paragraph) and the digital resulting value is:
analog read < 100 : no fire detected
analog read > 100 : fire detected
- Found in FAQ of dfrobot documentation : The range of Spectral Bandwidth of the sensor is 760nm to 1100nm, so it would detect any light whose Spectral Bandwidth is within 760-1100nm. After test, we found it can be effected not only by flame, but also by infrared radiations or neon lamps. It also can even be effected by phone’s flash.
Analog to Digital Converter (ADC) :
- The ADC use the potentiometer as analog input signal on send digital output data to the Pyboard via I2C interface.
- The ADC converter include one single I2C device. There is 4 analog input channels. In this app we use Input 0 (data signal). This configuration is setted with bit 14-12 of the configuration register.
- We select FS=+/-4.096V for the PGA (Programmable gain amplifier) of the ADC (cf. datasheet of the ADC) to fit with range [0-3.3V] of the potentiometer.
I2C Interface :
- I2C address are 0x90 (write) and 0x91 (read).
- The ADS1115 have a configuration register. The app write de configuration in the initialisation step, and read the configuration register to check that the write operation is ok. Configuration register is set as follow (cf. datasheet page 18/19/20).
bit 15 Operational status 0 (default) bit 14-12 Multiplexer config - INp=0 INn=GND 100 (INp=0 Nn=GND) bit 11-9 Gain amplifier FS= +/- 6.144V 001 (+/-4.06V) bit 8 Device operating mode 0 (continuous) bit 7-5 Data rate 111 (860SPS) bit 4 Comparator mode - Traditional 0 (default) bit 3 Comparator polarity - Active low 0 (default) bit 2 Nn-latching comparator 0 (default) bit 1-0 Disable comparator 11 (default) 0100001011100011 = 0x42E3
Sending values from the analog flame sensor.
hypos-tuto-222.c
/* ** hypos-tuto-222.c - Sample code for HyperpanelOS ======================= ** ** ** ** This simple code is located into the application container, it is run ** ** by the VMK sub-operating system. On the other hand, the I/O container ** ** runs all the drivers that are VMIO finite state machines. ** ** ** ** The goal of this small app is to make a fire detection system. ** ** ** ** ======================================================================= ** */ /* Documentation for I2C devices -------------------------------------------- Product used : - Ben-Gi Mini ADS115 Module 4 channels 16 bits I2C ADC www.amazon.fr/gp/product/B07PK1Z5H1 datasheet-ads115.pdf - Texas Instruments 16-bit Ananlog-to-Figital Converter - Flame Sensor V2 from DFRobot available at wiki.dfrobot.com/Flame_sensor_SKU__DFR0076 and also available in LattePanda Starter Sensor at www.lattepanda.com Flame sensor: - We use the Flame sensor SKU DFR0076 from dfrobot. The flame sensor can be used to detect fire or other wavelength at 760 nm ~ 1100 nm light. According to datasheet, this flame sensor probe angle of 60 degrees. Supply Voltage : 3.3V to 5V Detection range : 20cm (4.8V) ~ 100cm (1V) Rang of Spectral Bandwidth : 760nm to 1100nm - In this tutorial, we have some 5V free power pins available on the daughter board so we use one of them. - The flame sensor's operating temperature is -25 degrees Celsius to 85 degrees Celsius, in the course of the flame it should be noted that the probe distance from the flame should not be too close inorder to avoid damage. - There is no really specification about bandwidth signal (fire) and resulting analog value. So we act that "lower value" means "no fire" and "high values" means "fire". Detection range is 1V at 100cm so we set the ADC amplifier to this kind of range (cf. following paragraph) and the digital resulting value is: analog read < 100 : no fire detected analog read > 100 : fire detected - Found in FAQ of dfrobot documentation : The range of Spectral Bandwidth of the sensor is 760nm to 1100nm, so it would detect any light whose Spectral Bandwidth is within 760-1100nm. After test, we found it can be effected not only by flame, but also by infrared radiation or neon lamps. It also can even be effected by phone's flash. Analog to Digital Converter (ADC): - The ADC use the potentiometer as analog input signal et send digital output data to the Pyboard via I2C interface. - The ADC converter include one single I2C device. There is 4 analog input channels. In this app we use Input 0 (data signal). This configuration is setted with bit 14-12 of the configuration register. - We select FS=+/-4.096V for the PGA (Programmable gain amplifier) of the ADC (cf. datasheet of the ADC) to fit with range of the flame sensor. I2C Interface: - I2C address are 0x90 (write) and 0x91 (read). - The ADS1115 have a configuration register. The app write de configuration in the initialisation step, and read the configuration register to check that the write operation is ok. Configuration register is set as follow (cf. datasheet page 18/19/20). bit 15 Operational status 0 (default) bit 14-12 Multiplexer config - INp=0 INn=GND 100 (INp=0 Nn=GND) bit 11-9 Gain amplifier FS= +/- 6.144V 001 (+/-4.096V) bit 8 Device operating mode 0 (continuous) bit 7-5 Data rate 111 (860SPS) bit 4 Comparator mode - Traditional 0 (default) bit 3 Comparator polarity - Active low 0 (default) bit 2 Nn-latching comparator 0 (default) bit 1-0 Disable comparator 11 (default) 0100001011100011 = 0x42E3 Serial output: The ASY0 output is use to send alarm text message of "standard" or "fire" situation. */ /* Include files and external reference -------------------------------------*/ #include <hypos.h> // Hyperpanel OS basic interfaces. #include <drv_asy.h> // Prototype of "asy_write()". #include <drv_i2c.h> // Prototype of "i2c_*()". /* Internal defines of this module ------------------------------------------*/ #define TICK 1000 // Code for tick event. #define ADC_AD_W 0x90 // I2C dev address - ADC (write) #define ADC_AD_R 0x91 // I2C dev address - ADC (read) #define CONVERSION_REG 0x00 // I2C register - Converted value #define CONFIG_REG 0x01 // I2C register - Configuration #define INIT 0 // I2C command - ADC initialisation /* Internal global variables of this module --------------------------------*/ static int idto ; // Timer identifier. /* INIT command .............................................................*/ static const char init[] = // I2C command - ADC initialisation { /* Length-1, Address, Control byte, Data byte */ 3, ADC_AD_W , CONFIG_REG , // Write the configuration register 0x42, 0xE3, // Cf. datasheet page 19) 0, 0 , 0 , 0 , // End of command set } ; // static char *command[] = // I2C commands table { // (char*)&init[0] , // I2C command - INIT (char*)0 // End of list } ; // static const char *text[] = // Messages for flame detection { "No fire detected" , // Message for analog read < fire alert "*** FIRE! ***" , // Message for analog read > fire alert } ; /* Prototypes --------------------------------------------------------------*/ static int loop_app_task(void*) ; // Prototype static int wait_evt(void) ; // Prototype static void set_command(int) ; // Prototype /* Beginning of the code --------------------------------------------------- loop_app_tsk Application entry point */ /* Procedure loop_app_tsk -------------------------------------------------- Purpose : This is our task main loop. */ int loop_app_tsk (void *param) { int ev = TICK ; // Our event char mess[16] ; // Message to be sent on ASY0 unsigned char frame[16] ; // I2C read frame int ret = 0 ; // Return procedure code /* Step 1 - Start a timer that will send an event every second ..............*/ set_tto(CLOCK , // Timer mode: clock 1000 , // Duration in milliseconds TICK , 0 , // Event code and reserve field &idto ); // Timer identifier /* Step 2 - ADC initialisation ..............................................*/ asy_write(0,(unsigned char*)"Init ... ",9); set_command(INIT) ; // ADC initialization asy_write(0,(unsigned char*)"done\r\n",6); ret = i2c_read(0,ADC_AD_R , // Just for checking, read the register frame,2,CONFIG_REG); // we have just write. hsprintf(mess, "Configuration register 0x%02x%02x (%d)\r\n", frame[0],frame[1],ret); asy_write(0 , // Write on ASY0 the value of the (unsigned char*)mess , // configuration register. strlen(mess) ); // Count of bytes to be sent /* Step 3 - Main loop .......................................................*/ wait_ev : // Beginning of loop label if ( ev == TICK ) // If the event is the tick event { // frame[0]=0 ; // Reset frame. frame[1]=0 ; // Reset frame. ret=i2c_read(0,ADC_AD_R , // Read the current value get from frame,2 , // the ADC. CONVERSION_REG) ; // hsprintf(mess , // Message with the 16-bit value. "Flame sensor - Analog read 0x%03d - %s\r\n", frame[0] , // Conversion Voltage -> [0,127] (frame[0]<100)?text[0]:text[1],ret); // (0x67 max value read from // register with this model of // potentiometer). asy_write(0 , // Write on ASY0 (unsigned char*)mess , // the "mess" message strlen(mess) ); // Count of bytes to be sent } ev = wait_evt() ; // Unschedule until an event is received goto wait_ev ; // Wait for the next event return 0 ; // Return code of the procedure } /* Procedure wait_evt ------------------------------------------------------*/ /* Purpose : Unschedule until the next event is received, whatever it is. */ static int wait_evt (void) { int waitlist[1][3] ; // Parameter of "waitevt_task" int ret ; // Return code for "waiyevt_task" /***************************************************************************** * Step 1 : Build a list with one WAIT_CODEINT entry that will accept all * * ------ the event codes ranging from 0 to 20000. Then call * * "waitevt_task", we will be unscheduled until the next event will * * be received * *****************************************************************************/ waitlist[0][0] = WAIT_CODEINT ; // All events with waitlist[0][1] = 0 ; // a code between 0 waitlist[0][2] = 20000 ; // and 20000 waitevt_task(waitlist , // Address of waiting list 1 , // Size of "waitlist[]" 0 , // maximum waiting time = no 0 , // Do not purge previous events &ret ) ; // Return code /***************************************************************************** * Step 2 : Here we are scheduled again. The VMK has written into its * * ------ global variable "task_evt" a copy of the event that has * * scheduled us again. * *****************************************************************************/ return task_evt.code ; // Return event code } /* Procedure set_command ---------------------------------------------------*/ /* Purpose : Send a set of commands to I2C devices. */ static void set_command(int cmd) { i2c_write( 0 , // Controller number -1 , // Target I2C write address (unsigned char*)command[cmd], // Command 0 ); // List of option flags }