Tag Archives: iot

Détecteur de choc & TX 433Mhz pilotés avec le Microcontrôleur AVR ATTINY85

Circuit monté sur breadboard

Circuit monté sur breadboard

Avec la mise en veille (SLEEP_MODE_PWR_DOWN) et l’utilisation des interruptions , le circuit au repos ne consomme que 4µA avec un microcontrôleur Attiny85 (1€89 sur ebay) . J’alimente le circuit avec une pile bouton CR2032 3V achetée chez Ikea par lot de 8 pour quelques €uros. Le circuit devrait tourner beaucoup plus d’une année. 20160122_104647

300px-KY002

Détecteur de choc

A chaque détection de choc, le transmetteur 433Mhz émet un signal RF qui est reconnu par une Zibase en périphérique E10. Ce signal RF est défini dans le code de l’Attiny85 à la ligne n°46 (mySwitch.switchOn(‘e’, 3,2); // Test Zibase signal id E10) Dans mon circuit, je n’alimente pas le détecteur  en 5V, mais je l’utilise comme simple contacteur qui déclenche une interruption lorsqu’il y a détection de choc ( voir code: digitalWrite(WAKEUP_PIN, HIGH); // Activate internal pullup resistor ).

sku_334387_1
Tx 433MHz

Le détecteur,  grâce à la zibase, est intégré au système d’alarme . Présentement, il m’est inutile de monter une antenne de 17,3cm. En effet le signal est suffisamment puissant pour être reçu 5/5 à environ 7 mètres du récepteur RF ( la zibase, ou mon stick RTL-SDR connecté à un Raspberry Pi).

Détection niveau batterie faible

Un niveau de batterie faible est indiqué par la led qui flashe toutes les 8 secondes. Pour la détection de niveau de batterie faible, je me suis inspiré du post de Nick Gammon http://www.gammon.com.au/power

uint16_t readVcc(void) {
  uint16_t result;
  // Read 1.1V reference against Vcc
  ADMUX = (0<<REFS0) | (12<<MUX0);
  delay(2); // Wait for Vref to settle
  ADCSRA |= (1<<ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCW;
  return 1018500L / result; // Back-calculate AVcc in mV
}

Consommation du circuit avec un Arduino et Attiny85

sku_334387_1

TX 433.92MHz

  1. Attiny85: 4µA 
  2. Avec un arduino Nano : 43mA !!!
  3. Arduino M.J duino uno: 6,5mA
  4. Arduino XDRduino: 25mA
  5. Arduino Mini Pro: 3,5 mA . En ôtant la LED (on) et le régulateur de tension 5V, on pourrait tomber à moins d’1mA

RF Shock sensor Sketch_bb

Le script pour Attiny85

Pour programmer l’Attiny85 à l’aide d’un arduino, je me suis inspiré du post d’Erwan http://labalec.fr/erwan/?p=1508. Éventuellement, ne pas oublier de graver la séquence d’initialisation (bootloader) de l’Attiny85.

// https://blog.onlinux.fr/
//
//
//                           +-\/-+
//          Ain0 (D 5) PB5  1|    |8  Vcc
//          Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1 -
// LED +pin Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1 - Shock sensor pin
//                     GND  4|    |5  PB0 (D 0) pwm0 - RF433 tx pin
// 
// **** INCLUDES *****
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <RCSwitch.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define LOW_BATTERY_LEVEL 2500 //mV. Led will flash if battery level is lower than this value
#define WDT_COUNT  225  // wdt is set to 8s, 8x225=1800 seconds = 30 minutes

volatile boolean f_wdt = 0;
volatile byte count = WDT_COUNT;
volatile boolean f_int = 0;
volatile boolean lowBattery = 0;
volatile boolean switchState = HIGH;

const byte TX_PIN   = PB0;  // Pin number for the 433mhz OOK transmitter
const byte LED_PIN  = PB4;
const byte WAKEUP_PIN = PB1;  // Use pin 1 as wake up pin

RCSwitch mySwitch = RCSwitch();

/******************************************************************/
 
void setup()
{
  setup_watchdog(9);
  pinMode(TX_PIN, OUTPUT);
  pinMode(WAKEUP_PIN, INPUT);        // Set the pin to input
  digitalWrite(WAKEUP_PIN, HIGH);    // Activate internal pullup resistor  
  mySwitch.enableTransmit(TX_PIN);
  
  mySwitch.switchOn('e', 3,2);      // Test Zibase signal id E10
  
  lowBattery =  !(readVcc() >= LOW_BATTERY_LEVEL); // Initialize battery level value
  
  PCMSK  |= bit (PCINT1);  // set pin change interrupt PB1
  GIFR   |= bit (PCIF);    // clear any outstanding interrupts
  GIMSK  |= bit (PCIE);    // enable pin change interrupts  
  sei();         
}


// set system into the sleep state 
// system wakes up when watchdog is timed out
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out 
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9=8sec
void setup_watchdog(int ii) {

  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);   
  // set new watchdog timeout value   
  WDTCR = bb;   WDTCR |= _BV(WDIE); 
}
    
// Watchdog Interrupt Service / is executed when watchdog timed out 
ISR(WDT_vect) {   
  if (count >= WDT_COUNT) {
   f_wdt=true;  // set WDTl flag
   count=0;
  }
  count++;
} 

ISR (PCINT0_vect){
  f_int=true; // set INT flag
}
 
void loop()
{
  system_sleep();
  
  if (lowBattery)        // lowBattery is at setup().
    lowBatteryWarning(); // Flash for 1ms every 8s http://www.gammon.com.au/power
  
  
  if (f_int) {
    blink(2);
    cli();
    mySwitch.switchOn('e', 3,2);      // Zibase signal id E10
    f_int=false;  // Reset INT Flag
    sei();
  } 
  else if ( f_wdt ) {
    blink(5);
    cli(); // disable interrupts
    lowBattery = !(readVcc() >= LOW_BATTERY_LEVEL);
    f_wdt=false; // reset WDT Flag
    sei(); // enable interrupts
  }
    
}


void blink(int ii) {
  pinMode(LED_PIN, OUTPUT);
  for (byte i = ii ;  i > 0 ; i--){
     digitalWrite(LED_PIN, HIGH);
     delay(50);
     digitalWrite(LED_PIN, LOW); 
     delay(50);
  }
  
  pinMode(LED_PIN, INPUT); // reduce power
}

void lowBatteryWarning () {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite (LED_PIN, HIGH);  
  delay (1);       // mS        
  digitalWrite (LED_PIN, LOW);    
  //delay (999); 
  pinMode(LED_PIN, INPUT); // reduce power  
}

uint16_t readVcc(void) {
  uint16_t result;
  // Read 1.1V reference against Vcc
  ADMUX = (0<<REFS0) | (12<<MUX0);
  delay(2); // Wait for Vref to settle
  ADCSRA |= (1<<ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCW;
  return 1018500L / result; // Back-calculate AVcc in mV
}

Et la suite…

Le circuit pourrait ếtre encore plus miniaturisé en se passant du breadboard.
Maintenant il ne reste qu’à trouver un joli boîtier pour cacher toute l’électronique.
Malheureusement je n’ai pas d’imprimante 3D!

20160122_121130_cut

Le détecteur de choc et en haut le détecteur d’ouverture

Si vous avez des idées pour une solution esthétique, n’hésitez pas!

Détecteur de mouvement PIR & TX 433Mhz pilotés avec le Microcontrôleur AVR ATTINY85

PIR Atinny85 Sketch_bb

 

pir

Détecteur de mouvement PIR

Avec la mise en veille (SLEEP_MODE_PWR_DOWN) et l’utilisation des interruptions (INT0) , le circuit au repos ne consomme que 30µA avec un Attiny85 (1€89 sur ebay) . Avec le jeu de piles AAA ( en fait je n’en ai

Attiny85

Attiny85

mis que 3 en série), le circuit devrait tourner plus d’une année.

A chaque détection de mouvement, le transmetteur 433Mhz envoie une trame qui est reconnue par une Zibase en périphérique B15.

Le détecteur,  grâce à la zibase, est intégré au système d’alarme et,  avec  un scénario, il permet de gérer la lumière de la cuisine.

Consommation avec un Arduino

sku_334387_1

TX 433.92MHz

  1. Avec un arduino Nano : 43mA !!!
  2. Arduino M.J duino uno: 6,5mA
  3. Arduino XDRduino: 25mA
  4. Arduino Mini Pro: 3,5 mA . En ôtant la LED (on) et le régulateur de tension 5V, on pourrait tomber à moins d’1mA, mais ce sera toujours bien plus qu’un circuit à base de l’Attiny85. Il faudra que j’essaie!

Le script pour Attiny85

Pour programmer l’Attiny85 à l’aide d’un arduino, je me suis inspiré du post d’Erwan http://labalec.fr/erwan/?p=1508. Éventuellement, ne pas oublier de graver la séquence d’initialisation (bootloader) de l’Attiny85.

// **** INCLUDES *****
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include  

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


// Use pin 0 as wake up pin
const int wakeUpPin = 0;
volatile int ledState = LOW;
#define tx 1 // Pin number for the 433mhz OOK transmitter
#define pinLed 4
RCSwitch mySwitch = RCSwitch();

// set system into the sleep state 
void system_sleep() {
 cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF
 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
 sleep_enable();
 sleep_mode(); // System sleeps here

 sleep_disable(); // System continues here 
 sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}

void setup()
{
 pinMode(wakeUpPin, INPUT); 
 pinMode(pinLed, OUTPUT); 
 mySwitch.enableTransmit(tx);
 
 PCMSK |= bit (PCINT0); 
 GIFR |= bit (PCIF); // clear any outstanding interrupts
 GIMSK |= bit (PCIE); // enable pin change interrupts 
 sei();
}

ISR (PCINT0_vect) 
{
 ledState = digitalRead(0);
}

void loop() 
{

 system_sleep();

 if (ledState) {
   digitalWrite(pinLed, ledState);
   mySwitch.switchOn("01111", "00010"); // ZIBASE => B15 
   delay(500);
   digitalWrite(pinLed, !ledState);
 }

}

 

Le script pour Arduino

// **** INCLUDES *****
#include "LowPower.h"
#include  

// Use pin 2 as wake up pin
const int wakeUpPin = 2;
volatile int ledState = LOW;
#define tx 4 // Pin number for the 433mhz OOK transmitter

RCSwitch mySwitch = RCSwitch();

void wakeUp()
{
 // Just a handler for the pin interrupt.
 //Serial.println("RISING on D2");
 ledState = !ledState; 
 digitalWrite(13, ledState); 
 
}

void setup()
{
 // Configure wake up pin as input.
 // This will consumes few µA of current.
 pinMode(wakeUpPin, INPUT); 
 pinMode(13, OUTPUT); 
 Serial.begin(9600); // use the serial port
 mySwitch.enableTransmit(tx);
 
}

void loop() 
{
 attachInterrupt(0, wakeUp, CHANGE);
 // Enter power down state with ADC and BOD module disabled.
 // Wake up when pin changes
 LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); 

 
 // Disable external pin interrupt on wake up pin.
 detachInterrupt(0); 
 
 // Do something here
 // Example: Read sensor, data logging, data transmission.
 if (ledState) {
   Serial.println("RISING on D2");
   mySwitch.switchOn("01111", "00010"); // ZIBASE = A15 ?? 00 15 11 
 }
 else {
   Serial.println("FALLING on D2");
 }
 delay(500);

}

Sonde température DS18B20 1-Wire intégrée à la ZiBase via Raspberry Pi

 

 

Sonde 1-wire DS18B20

Sonde 1-wire DS18B20

raspizibase

 

 

 

 

 

Pour quelques €uros vous trouverez facilement sur internet des montages avec sonde déjà pré-cablée.

ds18b20 pré-cablée

ds18b20 pré-cablée

Installation Matériel

Sonde 1-wire ​DS18B20​

shema-branchement-DS18B20

Raspberry Pi

Zibase

Installation Logiciel

module ZiBase.py modifié ( ajout méthode setVirtualProbe )

def setVirtualProbe(self, id, value1, value2=0, type=17):
 """
 Cette commande permet au système HOST d’envoyer dans ZiBASE une information de sonde virtuelle
 comme si celle-ci était reçue sur la RF.
 Probe type: 
 17 : Scientific Oregon Type
 20 : OWL Type
 """
 req = ZbRequest()
 req.command = 11 # Virtual Probe Event
 req.param1 = 6
 req.param2 = id # Sensor ID (e.g; 4196984322
 req.param4 = type
 binStr = '00000000'+ dec2bin(value2 & 0xFF) + '00000000' + dec2bin(value1 & 0xFFFF)
 req.param3= int(binStr,2)
 #req.param3 = value1
 #print binStr, req.param3
 self.sendRequest(req)

Installer le  module w1thermsensor:  https://github.com/timofurrer/w1thermsensor.git

w1thermsensor.zip

crontab

crontab -l
 
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
MAILTO=ericxxxx@gmail.com


# m h dom mon dow command
*/2 * * * * cd /home/pi/python/weather; sudo python temp.py >> temp.log

Création sonde ZiBase

 

zibase_web.php

Détecteur de mouvement (PIR) du Raspberry Pi intégré à la ZiBASE – Part 2/2

Nous avons vu dans la partie 1, comment installer le module PIR,  lancer le script python pir.py et déclarer un périphérique virtuel sur la ZiBASE.

zibase

Nous allons voir maintenant comment déclarer notre script python comme un service linux qui sera démarré automatiquement à chaque reboot du Raspberry Pi.

Les fichiers nécessaires

Rappel: Les fichiers sont disponibles au téléchargement sur le site https://github.com/onlinux/Raspberry-Pi-PIR .Vous pourrez y télécharger l’ensemble du projet:

pi@raspi $ wget https://github.com/onlinux/Raspberry-Pi-PIR/archive/master.zip
pi@raspi ~ $ unzip master.zip 

ll-RAspberryLe fichier qui va nous permettre de déclarer notre script  python  comme service système est le fichier pir.

Il faut dans un premier temps copier ce fichier dans le répertoire /etc/init.d du Raspberry Pi et lui changer ses droits:

sudo cp pir /etc/init.d
sudo chmod 755 /etc/init.d

Copier le script python dans le répertoire /usr/local/bin

sudo cp pir.py /usr/local/bin
sudo chmod 755 /usr/local/bin/pir.py

Vous pouvez dès à présent exécuter  le script pour lancer le service :

sudo /etc/init.d/pir restart

execution-pir

Pour que le service soit exécuté à chaque reboot du Raspberry Pi, tapez:

sudo update-rc.d pir defaults

update-rc1

 

A ce stade, vous pouvez rebooter le Raspberry Pi, notre service sera lancé à chaque démarrage.

Le script pir

#! /bin/sh                                                                                                    
#                                                                                                                 
# Author: Eric Vandecasteele, 2014                                                                                
# https://blog.onlinux.fr                                                                                              
#                                                                                                                            
# /etc/init.d/pir                                                                                                            
#                                                                                                                                
### BEGIN INIT INFO                                                                                                                  
# Provides:          pir                                                                                                              
# Required-Start:                                                                                                                       
# Required-Stop:                                                                                                                           
# Default-Start:     2 3 4 5                                                                                                                
# Default-Stop:      0 1 6                                                                                                                   
# Short-Description: pir daemon drives the Passive Infra Red Motion Detector
# Description:       The pir daemon sends a http request on any Motion Detection Alarm
### END INIT INFO

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root

PATH=/bin:/usr/bin:/sbin:/usr/sbin
DAEMON=/usr/local/bin/pir.py

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/pir.pid

NAME=pir

test -x $DAEMON_OPTS || exit 0

. /lib/lsb/init-functions


do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started

        if pidofproc -p $PIDFILE "$DAEMON" > /dev/null 2>&1 ; then
                return 1
        fi
}

case "$1" in
  start)
     log_daemon_msg "Starting $NAME"
     do_start
     RET_STATUS=$?
     case "$RET_STATUS" in
        1)
           log_success_msg
           [ "$VERBOSE" != no ] && [ $RET_STATUS = 1 ] && log_warning_msg "Daemon was already running"
        ;;
        *)
           start-stop-daemon --start  --background --oknodo --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --exec $DAEMON  $DAEMON_OPTS 
           log_end_msg $?
        ;;
     esac
     ;;
  stop)
     log_daemon_msg "Stopping $NAME"
     start-stop-daemon --stop --pidfile $PIDFILE --retry 10
     log_end_msg $?
   ;;
  force-reload|restart)
     $0 stop
     $0 start
   ;;
  status)
     status_of_proc -p $PIDFILE $DAEMON $NAME  && exit 0 || exit $?
   ;;
 *)
   echo "Usage: /etc/init.d/pir {start|stop|restart|force-reload|status}"
   exit 1
  ;;
esac
exit 0

Le fichier log

Dans la partie 1, nous avons vu que dans le script pir.py nous avons défini notre fichier log comme /var/log/pir.log
pir-log

Copier le fichier  de configuration de la log logrotate.d/pir dans le répertoire /etc/logrotate.d

sudo cp logrotate.d/pir /etc/logrotate.d
/var/log/pir.log {
        daily
        missingok
        rotate 7
        compress
        delaycompress
        notifempty
        create 640 root adm
        sharedscripts
        postrotate
                /etc/init.d/pir restart > /dev/null
        endscript
}

La gestion de la logfile de notre service pir sera désormais prise en charge par le système.

Voilà, à ce stade le projet est terminé. Nous avons installé un service sur notre Raspberry Pi qui à chaque détection de mouvement va envoyer une requête http à la ZiBASE, afin d’alimenter notre détecteur de présence virtuel.pi-motion-plate-forme