📜 ⬆️ ⬇️

Wireless communications "smart home". Part two, practical

After writing a couple of big posts about “radioed” smart home, there were quite a few people who wanted to get code that would help deal with this topic in more detail.
For some reason I didn’t want to post my original version of the code - I prepared a “lightweight” version that would explain my main ideas.

In order to make the post the most spectacular and useful, today we are implementing a home mini-system (clock, calendar, weather, monitoring battery charge levels in sensors, etc.) consisting of one “main” module (with a large LED matrix in as an indicator), two autonomous sensors (will measure the temperature) and a time synchronization module via NTP.

First, a brief talk about the components of the project:

Shield MaTrix

Expansion card for Arduino Mega (there will be a separate post about the process of its creation, but a little later). This extension allows you to control the output of information on four 8x8 bicolor LED arrays, forming a single 32x8 field (the resolution is small, but the inscriptions are quite large).

Additionally, the board has:


The module was developed "from what was" and made as simple as possible for users. The display unit is built on well-known shift registers (74HD595D - LED control "in columns") and a demultiplexer (74HD138D - control "rows"). Naturally, dynamic display is used.

In order to make it even easier to use - a library was written with basic primitives (“display a line”, “creeping line”, brightness adjustment, there are several effects).

The shield itself does not contain an MK, you need to connect an “Arduino Mega” or a compatible clone to it (I used one ).

Shield MaTrix scheme is available by reference .
')
Sensor node

This is an arduino-compatible module built on the Atmega328 base, powered by one CR2032 lithium battery, having an on-board temperature sensor (MCP9700), a button, an LED, and three connectors for connecting possible extensions (sensors, etc.).

From the sensor features:


About the development of this module, too, I will write an article, if there is interest among readers.

In our case, to save the battery, we will use the MK with clocking from the internal oscillator at a frequency of 8 MHz and “ask” the MK to continue operating at reduced voltage (from 1.8V). To do this, in the boards.txt file, add the following lines:
s328o8.name=Sensor328 (int8MHz, 1.8V)

s328o8.upload.protocol=arduino
s328o8.upload.maximum_size=30720
s328o8.upload.speed=19200

s328o8.bootloader.low_fuses=0xe2
s328o8.bootloader.high_fuses=0xda
s328o8.bootloader.extended_fuses=0x06
s328o8.bootloader.path=atmega

s328o8.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex

s328o8.bootloader.unlock_bits=0x3F
s328o8.bootloader.lock_bits=0x0F

s328o8.build.mcu=atmega328p
s328o8.build.f_cpu=8000000L
s328o8.build.core=arduino
s328o8.build.variant=standard


UPD: 2.4. 1.8 1. :

s328o1.name=Sensor328p (int1MHz, 1.8V)

s328o1.upload.protocol=arduino
s328o1.upload.maximum_size=30720
s328o1.upload.speed=19200

s328o1.bootloader.low_fuses=0x62
s328o1.bootloader.high_fuses=0xda
s328o1.bootloader.extended_fuses=0x06
s328o1.bootloader.path=atmega

s328o1.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex

s328o1.bootloader.unlock_bits=0x3F
s328o1.bootloader.lock_bits=0x0F

s328o1.build.mcu=atmega328p
s328o1.build.f_cpu=1000000L
s328o1.build.core=arduino
s328o1.build.variant=standard


— , . , Arduino . avrdude ( avrdude GUI — ).

, « Sensor Node (SN) » — .
:
  • «» ,
  • 8
  • SN «» 1 8 , , ( — , «»)

( 20 ) 2.83.

, , , , 4 , , , , .

.

iBoard

. : 328, LAN Wiznet W5100, nrf24l01+, SD, .
( ) — .

nRF24l01+

RF-, 2.4. .
RF24 ( iBoardRF24).


, :

( ), - , , .

:
  1. Shield MaTrix: (iBoard — « /»), , , ( ), «» .
  2. Sensor Node: , . , ( «» ).
  3. iBoard: DHCP, NTP-, , / .


, , .
.



nRF24l01+ — , ( ) .

, « » 32 .
— , «» .
:
//     
typedef struct{         
  int SensorID;        //  
  int ParamID;         //   
  float ParamValue;    //  
  char Comment[16];    // 
}
Message;


, 32 .

(SensorID): Shield MaTrix — 100, Sensor Node 1 (SN1 — «») — 200, SN2 («») — 300, iBoard — 900.

, — , .

, «» , ( , «» 2 — ( — )).

, «» :
///     
typedef struct{
  float Value;         //  
  char Note[16];       // 
} 
Parameter;


(Value) float ( , ( , ) — ).
Note « » ( «TempIN, C» — ).

, (Parameter) «» (Message).

.

SN1 SN2. :
  1. setup() —
  2. loop():
    • , «»
    • RF-

( 8 ), ( ) 8 — , , 8- . 4 , , , 30 , .
— RF- ( powerDown() ).

, …

, «» :

Parameter MySensors[NumSensors+1] = {    //   (  )
  NumSensors, "SN1 (in)",            //   ""        
  0, "TempIN, C",                        //    
  0, "VCC, V",                           //   (   )
  0, "BATT"                              //  ,     (0 -  "", 1 - "")
};

Message sensor; 


«»:

Parameter MySensors[NumSensors+1] = {    //   (  )
  NumSensors, "SN1 (in&out)",        //   ""        
  0, "TempIN, C",                        //    
  0, "VCC, V",                           //   (   )
  0, "BATT",                             //  ,     (0 -  "", 1 - "")
  0, "TempOUT, C"                        //    
};

Message sensor;


«» (TempIN), (TempOUT), .

«» «» . «» () MCP9700 ( « » — , .

— , MCP9700 . ( — , , ). . ( ) «Analog»).

.

, MCP9700 , , .

, ( SN , 328).
( , , ).
:
long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif  

  delay(75); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}


.

, SN1 — 200:
//     
void calculateValue(){
  //    
  //  
  MySensors[2].Value = ((float) readVcc())/1000.0;
  
  //    (  3)
  MySensors[1].Value = (((float)analogRead(A3) * MySensors[2].Value / 1024.0) - 0.5)/0.01;
  
  //    2.4 -  "" (1)
  //   - " " (0)
  MySensors[3].Value = (MySensors[2].Value > 2.4) ? 1 : 0; 
  
  return;
}


SN2 («» — 300):
//     
void calculateValue(){
  //    
  //  
  MySensors[2].Value = ((float) readVcc())/1000.0;
  
  //    (  3)
  MySensors[1].Value = (((float)analogRead(A3) * MySensors[2].Value / 1024.0) - 0.5)/0.01;
  
  //    2.4 -  "" (1)
  //   - " " (0)
  MySensors[3].Value = (MySensors[2].Value > 2.4) ? 1 : 0; 
  
  //    (  1   "Analog")
  MySensors[4].Value = (((float)analogRead(A1) * MySensors[2].Value / 1024.0) - 0.5)/0.01;
  
  return;
}


, , «» .

- , ( 4 ) — «» (mode = 1) «» (mode = 2).
«» , 8 .
«» , 4 ( ).
«» 10 (.. 10 «» — ). , , .

, «» .

- « /» ( iBoard).
/ — .

, .
«» - / float.

: «yymm.dd», — «hhmm.ss». float.

, , « /»:
Parameter MySensors[NumSensors+1] = {    //   (  )
  NumSensors, "iBoard NTP",              //   ""        
  0, "Date (yymm.dd)",                   // 
  0, "Time (hhmm.ss)"                    // 
};

Message sensor; 


/ , (, , , — , 10 , ( )).

— , ( ):
#define TimeOffset 4  //   - GMT +4 ()


, iBoard SN, — RF24 (iBoard «» ).

, , — (« — — — »), «» — Shield MaTrix — , .

«»: , «» ( «» ), , , Shield MaTrix.

: , , — «». [0,«»] — map(...), «» ( 20 255, ).

«» :
  1. ( digit6x8future, )
  2. ( font6x8, )
  3. ( font6x8, (+)
  4. ( , ). .
  5. ( , ).

- , « » ( ) — — ( , ), : « (CR2032) !» , .


, :


?


  1. «» ( , MaTrix « »).
  2. SN (, ..).
  3. SN ( «» ).
  4. «» «» , « » .
  5. ( , iBoard: , «» SD- (, iBoard microSD) - , " " - , ).
  6. (, MaTrix (300 -> 100) - - ).

, .



:


P.S. , , ( — ).

Source: https://habr.com/ru/post/202898/


All Articles