Bezdrátový modul Warduxere: první použití

4. 5. 2016
Doba čtení: 9 minut

Sdílet

Postavili jste si nenáročné bezdrátové zařízení Warduxere? Je čas na úplně první použití úsporného bezdrátového modulu: rozblikání LED a měření napětí na baterii.

Kdo si postavil bezdrátové bateriové zařízení Warduxere podle našeho seriálu, jistě netrpělivě čeká na návod, jak ho používat.

Pro práci s Warduxere stačí z Internetu stáhnout Arduino IDE, které obsahuje vše potřebné. Stačí stažený archiv rozbalit, není třeba nic instalovat. Kromě všech potřebných komponent Arduino IDE obsahuje i množství příkladů jak pro samostatné Arduino, tak pro běžně dostupné rozšiřující desky (shieldy).

Warduxere má připraven odpor a pájecí plošky pro sběrnici one-wire, odporový dělič pro měření baterie, odpor a pájecí plošky pro analogové čidlo (např. fotorezistor). Další piny procesoru jsem vyvedl na pájecí plošky, aby se k procesoru dala připojit další zařízení a periferie, například různé typy LCD displejů, Ethernet, GSM moduly.

Konkrétní použití bude záviset hlavně na nápadech každého konstruktéra. Dále popíši vlastnosti, kterými se Warduxere odlišuje od Arduina. Před použitím knihoven zmíněných v následujících odstavcích je potřeba je rozbalit do adresáře arduino/libraries/.

Připojení

Pro propojení s PC je ideální USB-UART převodník, z kterého je zařízení i napájeno. Já používám převodník s čipem čipem CP2102 nebo FTDI 232RL. Čínský CH340 určitě také dobře poslouží.

Po propojení Warduxere s USB převodníkem již není třeba žádná další elektronika a Warduxere pak lze připojit k PC a používat spolu s Arduino IDE. Propojení je na obrázku, je potřeba správně připojit RX převodníku na TX procesoru.

U počítačů jako je Raspberry Pi a Banana Pi R1 jde Warduxere připojit přímo bez jakékoli další elektroniky, protože tyto počítače mají hardwarové sériové linky pracující s napěťovou úrovní 3,3V.

Pro nahrání programu do procesoru ve vývojovém prostředí slouží tlačítko upload. Po kliknutí na něj IDE nejdříve provede reset procesoru, pomocí vývodu DTR (RTS). Po resetu se jako první spustí zavaděč, který chvíli čeká na nahrání programu.

Dioda

Funkčnost zařízení jde jednoduše vyzkoušet blikáním diody. Obvykle bývá dioda na vývodu CPU 17 (označení dle zvyku Arduina je D13), ale tam je připojen wireless modul. Proto u Warduxere je LED připojena na vývodu procesoru 32 (Arduino D2). Použití je zřejmé ze vzorového programu  Blink.

/*
  Warduxere - Blink

  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.

  Author: Bc. Josef Jebavý
  web: http://www.xeres.cz
  about project: http://multi.xeres.cz/programovani/wireless-arduino-low-power-consumption


 */

#define PINLED 3

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 3 as an output.
  pinMode(PINLED, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(PINLED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(PINLED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

Wireless

Možnosti konfigurace bezdrátové komunikace jsou rozsáhlé. Nejpodstatnější je, že komunikace je paketově orientovaná s bufferem 64 bajtů. Rychlost komunikace může být 0,123 až 256 kbps, modulace: FSK, GFSK a OOK. Je možno provozovat i rozsáhlé MESH sítě.

Pro příklad uvádím jen ten nejzákladnější typ komunikace, s kterým jde ověřit funkčnost zařízení. K vyzkoušení potřebuje dva moduly Warduxere a do každého nahraje jeden z programů. Viz níže uvedené vzorové programy Wireless-client a Wireless-server, které jsou i na GitHubu.

Před vyzkoušením programu je potřeba do Arduino IDE doplnit knihovnu RF22.

Klient

/*
 Warduxere- Wireless client
 Example of wireles comunication.
 Tested on Warduxere: Atmega328 and SI4432

 This example code is in the public domain.


 about Warduxere: http://multi.xeres.cz/programovani/wireless-arduino-low-power-consumption


 */

#include <SPI.h>
#include <RH_RF22.h>

// Singleton instance of the radio driver
RH_RF22 rf22;

void setup()
{
  Serial.begin(9600);
  if (!rf22.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, 0.05MHz AFC pull-in, modulation FSK_Rb2_4Fd36
}

void loop()
{
  Serial.println("Sending to rf22_server");
  // Send a message to rf22_server
  uint8_t data[] = "Hello World!";
  rf22.send(data, sizeof(data));

  rf22.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF22_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf22.waitAvailableTimeout(500))
  {
    // Should be a reply message for us now
    if (rf22.recv(buf, &len))
    {
      Serial.print("got reply: ");
      Serial.println((char*)buf);
    }
    else
    {
      Serial.println("recv failed");
    }
  }
  else
  {
    Serial.println("No reply, is rf22_server running?");
  }
  delay(400);
}

Server

/*
 Warduxere - Wireless server
 Example of wireles comunication.
 Tested on Warduxere: Atmega328 and SI4432

 This example code is in the public domain.

 about Warduxere: http://multi.xeres.cz/programovani/wireless-arduino-low-power-consumption


 */



#include <SPI.h>
#include <RH_RF22.h>

// Singleton instance of the radio driver
RH_RF22 rf22;

void setup()
{
  Serial.begin(9600);
  if (!rf22.init())
    Serial.println("init failed");
  // Defaults after init are 434.0MHz, 0.05MHz AFC pull-in, modulation FSK_Rb2_4Fd36
}

void loop()
{
  if (rf22.available())
  {
    // Should be a message for us now
    uint8_t buf[RH_RF22_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    if (rf22.recv(buf, &len))
    {
//      RF22::printBuffer("request: ", buf, len);
      Serial.print("got request: ");
      Serial.println((char*)buf);
//      Serial.print("RSSI: ");
//      Serial.println(rf22.lastRssi(), DEC);

      // Send a reply
      uint8_t data[] = "And hello back to you";
      rf22.send(data, sizeof(data));
      rf22.waitPacketSent();
      Serial.println("Sent a reply");
    }
    else
    {
      Serial.println("recv failed");
    }
  }
}

Další praktické příklady použití wireless čipu SI4432 s knihovnou RadioHead RF22 čtenář najde v dokumentaci wireless knihovny RF22.

Úsporné režimy

Procesor umí několik úsporných režimů. Neúspornější režim procesoru je spánek, pro větší úsporu je potřeba uspat i jednotlivé částí procesoru jako je A/D převodník a vypnout Brown-out Detector (BOD). Často stačí ponechat běžet pouze watchdog, který vygeneruje přerušení pro probuzení. Periferie je potřeba také uspat, zde se jedná pouze o Wireless modul, který se na žádost umí uspat. Při uspávání zařízení je tedy potřeba uspat jak vlastní procesor, tak wireless část. Jednoduchý příklad s uspáním je v programu Sleep:

/*
 Warduxere - Sleep
 Example of sleeping and saving power

 This example code is in the public domain.

 Author: Bc. Josef Jebavý
 web: http://www.xeres.cz
 about project: http://www.multi.xeres.cz/programovani/wireless-arduino-low-power-consumption


 */



#include <avr/sleep.h>
#include <avr/wdt.h>
#include <SPI.h>
#include <RH_RF22.h>

// Singleton instance of the radio driver
RH_RF22 rf22;
#define LED 3

// watchdog interrupt
ISR(WDT_vect)
{
  wdt_disable();  // disable watchdog
}

void myWatchdogEnable(const byte interval)
{

  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS);

  int previousADCSRA = ADCSRA;
  ADCSRA &= ~(1<<ADEN); //Disable ADC
  ACSR = (1<<ACD); //Disable the analog comparator
  DIDR0 = 0x3F; //Disable digital input buffers on all ADC0-ADC5 pins
  DIDR1 = (1<<AIN1D)|(1<<AIN0D); //Disable digital input buffer on AIN1/0


  //toto nejde zkompilovat pro atmega8
  MCUSR = 0;                          // reset various flags
  WDTCSR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCSR =  0b01000000 | interval;    // set WDIE, and appropriate delay

  wdt_reset();
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_mode();            // now goes to Sleep and waits for the interrupt

  //zapnuti ADC
  ADCSRA = previousADCSRA;
}

void setup()
{


  pinMode (LED, OUTPUT);

  PRR = bit(PRTIM1);                           // only keep timer 0 going
  // ADCSRA &= ~ bit(ADEN);
  // bitSet(PRR, PRADC);
  rf22.init();
}


void loop()
{


  // awake
  digitalWrite (LED, HIGH);
  delay (4000);

  //not sleeping not lihgt
  digitalWrite (LED, LOW);
  delay (4000);


   //blink before sleep
  digitalWrite (LED, HIGH);
  delay (200);
  digitalWrite (LED, LOW);

  //sleep wireless module
  rf22.sleep();
  // sleep 8 seconds
  myWatchdogEnable (0b100001);
  // sleep bit patterns:
  //  1 second:  0b000110
  //  2 seconds: 0b000111
  //  4 seconds: 0b100000
  //  8 seconds: 0b100001

}

Kdo nechce řešit nastavení uspávání sám, ten může použít knihovnu Low-Power. Příklad uspání zařízení s použití knihovny Low-Power je ve sketchi Sleep2:

/*
 Warduxere - Sleep
 Example of sleeping and saving power

 This example code is in the public domain.

 Author: Bc. Josef Jebavý
 web: http://www.xeres.cz
 about project: http://www.multi.xeres.cz/wireless-arduino-low-power-consumption


 */




#include <SPI.h>
#include <RH_RF22.h>
#include "LowPower.h"

// Singleton instance of the radio driver
RH_RF22 rf22;
#define LED 3





void setup()
{


  pinMode (LED, OUTPUT);

  rf22.init();
}


void loop()
{


  // awake
  digitalWrite (LED, HIGH);
  delay (4000);

  //not sleeping not lihgt
  digitalWrite (LED, LOW);
  delay (4000);


   //blink before sleep
  digitalWrite (LED, HIGH);
  delay (200);
  digitalWrite (LED, LOW);

  //sleep wireless module
  rf22.sleep();
  // sleep 8 seconds
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
 //   LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,                 SPI_OFF, USART0_OFF, TWI_OFF);
//  myWatchdogEnable (0b100001);
  // sleep bit patterns:
  //  1 second:  0b000110
  //  2 seconds: 0b000111
  //  4 seconds: 0b100000
  //  8 seconds: 0b100001

}

Baterie

Stav baterie je zjišťován měřením napětí na děliči 1:1 pomoci analogově digitálního převodníku, který je v CPU. Takto řešeným zapojením se zjišťuje skutečné napětí na baterii. U jiných řešení, jsem se setkal s problémem, kde se napětí baterie měřilo až za 3V stabilizátorem. Takže se nevědělo, jaké je napětí na baterii, což byl problém, obzvláště při použití Li-Pol/Ion baterií. Díky měření napětí na děliči, na který je přímo připojena baterie, je tak možnost připojit například tři články NiMH nebo jeden článek Li-Pol/Ion nebo i jiné typy baterií a úpravou softwaru lze lehce dosáhnout konkrétních potřeb pro hlídání stavu baterie.

Pro přesné měření baterie je potřeba také mít přesný dělič. Základní řady vyráběných odporů mají toleranci ±5%, ale tyto méně přesné odpory mohou udělat značnou chybu v měření. V nejhorším možném případě až ±10%, což by bylo u 4V baterie 0,4 V, a to je opravdu hodně. Pro vyhodnocení stavu baterií typu Li-Pol/Ion je to nepřijatelné. Proto je potřeba použít přesné odpory s tolerancí ± 0,1 % případně ± 0,5 %. Ale není hned nutné kupovat drahé přesné odpory. Pro výrobu několika wireless modulů dostačuje přeměřit odpory a vybrat do páru odpory o stejné hodnotě.

Měření napětí baterie je ve vzorovém programu Battery.

ict ve školství 24

/*
  Warduxere - Battery

 Get battery status
 This example code is in the public domain.

 Author: Bc. Josef Jebavý
 web: http://www.xeres.cz
 about project: http://multi.xeres.cz/programovani/wireless-arduino-low-power-consumption


 */

#define PINBAT A1
// the setup routine runs once when you press reset:
void setup() {

  Serial.begin(9600);

  pinMode(PINBAT, INPUT);


}

// the loop routine runs over and over again forever:
void loop() {


  //mereni baterie
  int sensorValue=analogRead(PINBAT);
  byte bat=0;

  // na LDO je ubytek napeti 0.178V takze pod 3.478V na baterii uz procesor a ADC bude napajen mene jak 3.3V
  // pro 3.3V arduino a delic 1:1 bude cislo odpovidat napeti na baterii:
  // 528 - 3.40V
  // 539 - 3.478V - hranice pro spravne napajeni
  // 550 - 3.544
  // 559 - 3.60V - hranice pro li-pol/ion baterii

  if (  sensorValue>558) {
    bat=1;
  }



  Serial.print("battery:");
  Serial.print(bat);
  Serial.print(";value:");
  Serial.print(sensorValue);
  Serial.print(";V:");
  double d =3.3/1024*sensorValue*2;
  Serial.print(d,4);
  Serial.println();

  delay(1000);
}

Závěr

Vyzkoušet všechny příklady lze lehce, pokud máte doma Arduino Pro Mini 3,3V 8MHz nebo mikroprocesor Atmega 328P a připojíte Wireless modul DRF4432F20, případně i jiný s čipem SI4432. Vše se dá vyzkoušet s pár součástkami, které zapojíte podle schématu. Jen nesmíte očekávat malou spotřebu zařízení.

Čistokrevní programátoři, kteří si nedokázali poradit s návrhem hardwaru, doposud jen hledali úsporné bateriově napájené bezdrátové zařízení. Nyní mají konečně možnost začít vytvářet programy pro bezdrátové sítě.

Autor článku

Josef Jebavý je profesí linuxový admin a vývojář softwaru, ale zabývá se i hardwarem a elektronikou. Mimo dílnu a počítačové pracoviště se obvykle věnuje sportu.