Category Archives: Zibase

Détecteur de choc & TX 433Mhz pilotés avec 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 Attiny85 (1€89 sur ebay) . J’alimente le circuit avec une pile bouton CR2032 3V achété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 signaf 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 suffisament puissant pour être reçu 5/5 à environ 7m du récepteur RF ( la zibase, ou mon stick RTL-SDR connecté à un RaspberryPi).

Détection niveau batterie faible

Un niveau de batterie faible est indiqué par la led qui flashe toutes les 8 s. 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// http://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 miniaturé 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!