Stránka 1 z 3

Arduino a bezdratove moduly 433Mhz

Napsal: 03 pro 2015, 16:50
od jiri255
Zdravím,
chtěl bych někoho požádat o kontrolu programů, řeším odesílání dat z Arduino UNO na Arduino MEGA pomocí 433Mhz modulů.
Arduino UNO je jako vysílač a k němu mám připojené čidlo teploty ds18b20, které mi na serial vypisuje aktuální teplotu to funguje a odesílá ji pomocí programu níže na druhé ARDUINO

Kód: Vybrat vše

#include <LwTx.h>
#include <EEPROM.h>
#include <OneWire.h>   //knihovna pro teplomer
 
byte data[] = {0,0,0,0,0,0,0,0,0,0};
OneWire  ds_1(9);  // čidlo 1

//--------------------------------zacatek teplomeru_1
float teplomer1() {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius_1, fahrenheit_1;
 
  if ( !ds_1.search(addr)) {
   // Serial.println("No more addresses.");
    Serial.println();
    ds_1.reset_search();
    delay(250);
    //return;
  }
 
  //Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    //Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
    //  return;
  }
 
  ds_1.reset();
  ds_1.select(addr);
  ds_1.write(0x44, 1);        // start conversion, with parasite power on at the end
 
  present = ds_1.reset();
  ds_1.select(addr);   
  ds_1.write(0xBE);         // Read Scratchpad

  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds_1.read();
    //Serial.print(data[i], HEX);
    Serial.print(" ");
  }

  Serial.println();

  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius_1 = (float)raw / 16.0;
  fahrenheit_1 = celsius_1 * 1.8 + 32.0;

  float stupne_1 = celsius_1;
  return stupne_1;
   }
//------------------------------------konec teplomeru_1


void setup()
{
  // Zapne ser. komunikaci
  Serial.begin(9600);

  // Data do vysílače jsou na pin 3.
  // Další číslo je počet opakovaní vysílaní
  // za sebou, v našem připadě 2x

  lwtx_setup(3, 4, 0, 140);
   Serial.println("nastaveni setupu"); 
}

void loop()
{
  int hodnota = teplomer1();
       Serial.println(teplomer1());
       
       data[9] = hodnota;
       data[8] = hodnota >> 8;   
 // když je vysílač nezaneprázdněn
  if (lwtx_free())

   {
   lwtx_send(data);
   // odešle zprávu na serial o odeslání
   Serial.println("Data odeslana");

   delay(5000);

   }

}


v přijímači což je Arduino MEGA mám program níže, který by měl
na serial vypisovat teplotu poslanou z Arduino UNO

Kód: Vybrat vše

#include <LwRx.h> 
#include <EEPROM.h>

int teplota = 0;

void setup() {
  // nastaví datový vývod přijmače na pin 2
  lwrx_setup(2);
  // zapne seriovou komunikaci
  Serial.begin(9600);
  Serial.println("konec setupu");
  }
 
void loop() {

  // proměná pro 10 hodnot
  byte data[10];

  // proměnná pro delku dat
  byte delka = 10;

  //když jsou přijata data
  if (lwrx_message())
    {

    // ulož data do promené data
    lwrx_getmessage(data,delka);   

 teplota = data[9] + (data[8] >>8);
      Serial.print(" ");
    Serial.println(teplota);
  }
  delay(10000);
  }


Je to celé funkční UNO ukazuje teplotu a odešle ji, MEGA ji přijme
jenže tady nastává problém :-(
UNO mi ukazuje teplotu např: 23.81, ale MEGA mi zobrazí jen to 23
a to ".81" mi tam chybí a není mi úplně jasné, ve kterém programu
mám chybu? Možná, že to mám zbytečně složité a šlo by to jednodušeji
mohl by mi s tím někdo prosím poradit?

Předem děkuji za případnou pomoc

Napsal: 03 pro 2015, 17:08
od Cowley
Zkus vynasobit na vysilaci hodnotu k odeslani treba 1000. Na prijimaci to pak udelej opacne ze prijaty parametr vydelis 1000. Zbavis se te desetinne tecky v prenosu. Mozna je to jen formatem toho parametru.

Napsal: 03 pro 2015, 17:58
od frpr666
No to je jasné. Máš problém se synchronizací. Vysílač má delay(5000), tak vysílá "zprávu" každých 5 sekund.
Příjmač má delay(10000), tak čte jednou za 10 sekund. Tj. přijme 2x "zprávu". Potom záleží, jak je napsaná knihovna LwRx.
Vypadá to, že v interruptu připojeného na pin, čte příchozí data a ukládá je jako bajty do bufferu.
Bohužel, když máš v bufferu dvě zprávy, nejde nijak rozlišit, kde "zpráva" začíná a kde končí.
Podívej se na vzorové příklady s touto knihovnou. Kombinují tam při čtení i funkci millis(), pomocí které lze "udělat" jakousi synchronizaci.

Napsal: 03 pro 2015, 18:04
od Cowley
Muzes sem dat odkaz na ty moduly 433MHz? Diky.

Napsal: 03 pro 2015, 18:46
od jiri255
[url]
http://arduino8.webnode.cz/news/lekce-2 ... 33-92-mhz/
[/url]
zde je odkaz odkud jsem čerpal a jsou tam vyfocené i ty moduly
jen oni pracujou s tlačítkama a já potřebuju teplotu

Napsal: 03 pro 2015, 18:58
od jiri255
dal jsem si do serialu tu hodnotu a je to taky jen 23, takže to vypadá, že se odesílá jen 23 a proto mi přijímač nic víc nezobrazí asi je tam chyba v tom co odchází

Kód: Vybrat vše

lwtx_send(data);

Napsal: 03 pro 2015, 20:02
od Cowley
Zaveď si pevnou proměnnou "data" třeba
float data = 23.50;

pak si dej celej teploměr bokem za // a vyzkoušej si posílat pořád dokola jen


lwtx_send(data);
delay(5000);

a uvidíš, kde se ti to ztrácí...
Já si myslím, že to bude formátem, buď to budeš posílat jako řetězec nebo jako čísla.
Zkoušel sis posílat třeba text "Ahoj" ?

Synchronizace může hrát taky roli, ale modul, jak jsem četl, pracuje v knihovně s přerušením, tak by se dal program upravit tak, aby vždy když něco zachytí, odeslal zachycené do proměnné a až na to v programu přijde řada, tak se to nechá zobrazit nebo zpracovat dál...

EDIT: tohle zřejmě nepůjde, protože jsem si dostatečně nepročetl ten tutoriál...
Měl jsem za to, že to bude běhat na podobném principu jako SoftwareSerial..., omlouvám se - mazat to nebudu, ať nenaruším průběh diskuse :)

Napsal: 03 pro 2015, 20:13
od Honza_dy
Není problém v tom int teplota? Já bych dal float teplota

Napsal: 03 pro 2015, 20:18
od Cowley
Trochu jsem pročetl ten odkaz na tutoriál a viděl bych to tak, že by se dala teplota odesílat ve dvou pozicích (celé číslo v jednom a desetiny v druhém) a potom to po přijetí zase složit.
V principu se zdá, že se do jedné buňky (byte[]) dá uložit jen číslo 0-15.

V tom tutoriálu je ale naznačeno, jak předat hodnoty větší než 15 i větší než 255, proto ti nic nebrání zbavit se v přenosu té desetinné čárky vynásobením třeba 100, odeslat to jako velké celé číslo a po příjmu si to převést na (float prijatahodnota) a zase to vydělit tou 100.

Kód: Vybrat vše

rozložení před vysláním
 unsigned int hodnota = 46795;
 data[9] = hodnota;
 data[8] = hodnota >> 4;
 data[7] = hodnota >> 8;
 data[6] = hodnota >> 12;
----------------------------
složení po příjmu

// spojí rozlozenou hodnotu
// dvou 4-bitových cisel do 8-bitového
teplota = data[9] + (data[8] << 4); 

Napsal: 03 pro 2015, 20:19
od Habesan
A překvapuje to někoho???

Jestli někdo pojmenuje typ proměnné byte a bude mít jiný počet bitů než 8, tak zaslouží vytahat.

Napsal: 03 pro 2015, 20:33
od Cowley
Habesan píše:A překvapuje to někoho???

Jestli někdo pojmenuje typ proměnné byte a bude mít jiný počet bitů než 8, tak zaslouží vytahat.


Měl jsem na mysli celé číslo, a ne desetinné :) , v rámci toho jejich protokolu, ale to jsem psal už před 3 hodinama :)

Napsal: 03 pro 2015, 21:14
od Cowley
Můžeš mi zkusit toto:

Kód: Vybrat vše

// vysilac

#include <LwTx.h>
 #include <EEPROM.h>
 #include <OneWire.h>   //knihovna pro teplomer
   
 byte data[] = {0,0,0,0,0,0,0,0,0,0};
 OneWire  ds_1(9);  // čidlo 1

 //--------------------------------zacatek teplomeru_1
 float teplomer1() {
   byte i;
   byte present = 0;
   byte type_s;
   byte data[12];
   byte addr[8];
   float celsius_1, fahrenheit_1;
   
   if ( !ds_1.search(addr)) {
    // Serial.println("No more addresses.");
     Serial.println();
     ds_1.reset_search();
     delay(250);
     //return;
   }
   
   //Serial.print("ROM =");
   for( i = 0; i < 8; i++) {
     Serial.write(' ');
     //Serial.print(addr[i], HEX);
   }

   if (OneWire::crc8(addr, 7) != addr[7]) {
       Serial.println("CRC is not valid!");
     //  return;
   }
   
   ds_1.reset();
   ds_1.select(addr);
   ds_1.write(0x44, 1);        // start conversion, with parasite power on at the end
   
   present = ds_1.reset();
   ds_1.select(addr);   
   ds_1.write(0xBE);         // Read Scratchpad

   Serial.print(" ");
   for ( i = 0; i < 9; i++) {           // we need 9 bytes
     data[i] = ds_1.read();
     //Serial.print(data[i], HEX);
     Serial.print(" ");
   }

   Serial.println();

   int16_t raw = (data[1] << 8) | data[0];
   if (type_s) {
     raw = raw << 3; // 9 bit resolution default
     if (data[7] == 0x10) {
       // "count remain" gives full 12 bit resolution
       raw = (raw & 0xFFF0) + 12 - data[6];
     }
   } else {
     byte cfg = (data[4] & 0x60);
     // at lower res, the low bits are undefined, so let's zero them
     if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
     else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
     else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
     //// default is 12 bit resolution, 750 ms conversion time
   }
   celsius_1 = (float)raw / 16.0;
   fahrenheit_1 = celsius_1 * 1.8 + 32.0;

   float stupne_1 = celsius_1;
   return stupne_1;
    }
 //------------------------------------konec teplomeru_1


 void setup()
 {
   // Zapne ser. komunikaci
   Serial.begin(9600);

   // Data do vysílače jsou na pin 3.
   // Další číslo je počet opakovaní vysílaní
   // za sebou, v našem připadě 2x

   lwtx_setup(3, 4, 0, 140);
    Serial.println("nastaveni setupu"); 
 }

void loop()
 {
   unsigned int hodnota = teplomer1() * 100;
        Serial.println(teplomer1());
         
        data[9] = hodnota;
        data[8] = hodnota >> 4;
        data[7] = hodnota >> 8;
        data[6] = hodnota >> 12;
   
  // když je vysílač nezaneprázdněn
   if (lwtx_free())

    {
    lwtx_send(data);
    // odešle zprávu na serial o odeslání
    Serial.println("Data odeslana");

    delay(5000);

    }

 }


Kód: Vybrat vše

// prijimac

#include <LwRx.h>
 #include <EEPROM.h>

 unsigned int prijem = 0;
 float teplota = 0;
 

 void setup() {
   // nastaví datový vývod přijmače na pin 2
   lwrx_setup(2);
   // zapne seriovou komunikaci
   Serial.begin(9600);
   Serial.println("konec setupu");
   }
   
 void loop() {

   // proměná pro 10 hodnot
   byte data[10];

   // proměnná pro delku dat
   byte delka = 10;

   //když jsou přijata data
   if (lwrx_message())
     {

     // ulož data do promené data
     lwrx_getmessage(data, &delka);   

  prijem = data[9] + (data[8] << 4) + (data[7] << 8) + (data[6] << 12);

teplota = prijem/100;
       Serial.print(" ");
     Serial.println(teplota);
   }
   delay(10000);
   }

Napsal: 03 pro 2015, 21:19
od Cowley
Ještě koukám, zda se v programu u vysílače netlučou ty dva data[] parametry, jeden je pro přenos a druhej pro teploměr :(

Modul 433MHz sice doma nemám, ale začíná se mi líbit :)

Samozřejmě bude potřeba zapracovat i záporné hodnoty naměřené teploty.
Ty ale nebude problém umístit do rezervní buňky data[0], třeba jako parametr 1 pro mínus a parametr 0 pro plus.

Napsal: 03 pro 2015, 21:35
od Cowley
frpr666 píše:... Bohužel, když máš v bufferu dvě zprávy, nejde nijak rozlišit, kde "zpráva" začíná a kde končí....


Přijímač zapisuje pořád do stejných buněk, proto když čte jednou za 10s, přijde o hodnotu která tam byla vyslaná a uložená před 5-ti vteřinama, jinak se nic neděje.

Pokud teda nepřijde během 5-ti sekund ze zimy pařák :)

Napsal: 04 pro 2015, 16:05
od jiri255
nahrál jsem tam ty programy výše a na přijímači vidím 0.00 pořád dokola po těch 10s a přitom na vysílači (ještě jsem si tam přidal)

Kód: Vybrat vše

Serial.println(hodnota);

vidím v serialu teplotu třeba 23.56 a hodnotu 2356, ale přijímač zobrazuje
pořád jen to 0.00