Ho trovato questo codice per "compattare" i valori dei sensori (Double e Float) in valori interi per poter mandare il messaggio senza problemi (max 12byte ).
#include <ArduinoLowPower.h>
#include <SigFox.h>
#include <Wire.h>
#include <Adafruit_INA219.h>
#include "BMP280.h"
#define SLEEPTIME 1*60*1000
#define UINT16_t_MAX 65536
#define INT16_t_MAX UINT16_t_MAX/2
typedef struct __attribute__ ((packed)) sigfox_message {
int16_t Current_mA;
int16_t Temperature;
uint16_t voltIn;
} SigfoxMessage;
// Stub for message which will be sent
SigfoxMessage msg;
Adafruit_INA219 ina219(0x40);
BMP280 bmp;
int debug = true;
int PinY = 1;
int PinG = 0;
int analogInputVoltage = A0;
char result;
float current_mA = 0;
double T,P;
float vin = 0.0;
float vout = 0.0;
float R1 = 47000;
float R2 = 10000;
int value = 0;
void setup() {
pinMode(PinY,OUTPUT);
pinMode(PinG,OUTPUT);
pinMode(analogInputVoltage, INPUT);
Serial.begin(9600);
if (!SigFox.begin()) {
//something is really wrong, try rebooting
reboot();
}
SigFox.end();
if (debug == true) {
// Enable debug prints and LED indication if we are testing
SigFox.debug();
}
uint32_t currentFrequency;
ina219.begin();
ina219.setCalibration_16V_400mA();
Serial.println("Measuring voltage and current with INA219 ...");
if(!bmp.begin()){
Serial.println("BMP init failed!");
while(1);
}
else {
Serial.println("BMP init success!");
}
bmp.setOversampling(4);
LowPower.attachInterruptWakeup(RTC_ALARM_WAKEUP, ledOn, CHANGE);
}
void loop() {
current_mA = ina219.getCurrent_mA();
result = bmp.startMeasurment();
value = analogRead(analogInputVoltage);
vout = (value * 3.3) / 1024.0;
vin = vout / (R2/(R1+R2));
if(vin<0.09) {
vin = 0.0;
}
if(result!=0){
delay(result);
result = bmp.getTemperatureAndPressure(T,P);
}
else {
Serial.println("Error.");
}
msg.Current_mA = convertoFloatToInt16(current_mA,60,-60);
msg.Temperature = convertoFloatToInt16(T,60,-60);
msg.voltIn = convertoFloatToUInt16(vin,25);
SigFox.begin();
delay(100);
SigFox.status();
delay(1);
SigFox.beginPacket();
SigFox.write((uint8_t*)&msg,12);
int ret = SigFox.endPacket();
SigFox.end();
if (debug == true) {
if (ret == 0) {
Serial1.println("Transmission ok");
digitalWrite(PinY,LOW);
digitalWrite(PinG,HIGH);
} else {
Serial1.println("No transmission");
digitalWrite(PinY,HIGH);
digitalWrite(PinG,LOW);
}
}
LowPower.sleep(SLEEPTIME);
}
void reboot() {
NVIC_SystemReset();
while (1);
}
void ledOn() {
digitalWrite(PinG,LOW);
digitalWrite(PinY,LOW);
}
int16_t convertoFloatToInt16(float value, long max, long min) {
float conversionFactor = (float) (INT16_t_MAX) / (float)(max - min);
return (int16_t)(value * conversionFactor);
}
uint16_t convertoFloatToUInt16(float value, long max) {
float conversionFactor = (float) (UINT16_t_MAX) / (float)(max);
return (uint16_t)(value * conversionFactor);
}
Questo è quello che prevede la funzione SigFox.write:
Description
Sends binary data to the SigFox's backend. This data is sent as a byte or series of bytes;
Ora mi sono trovato con il messaggio inviato che dovrebbe essere in forma esadecimale e non riesco a riconvertirlo in formato decimale, cioè ai valori standard leggibili.
Esempio: "f3ff591ae10100000000043d"
Qualcuno può aiutarmi a decodificarlo?? E spiegarmi come fare...
Grazie
questi non sono 12 byte...
dovrebbero essere: f3ff591ae101 per cui andrebbero separati in
current_ma= f3ff
temperature= 591a
voltin=e101
che poi con la formula inversa dovrebbero darti i valori di partenza
tipo:
Provo a fare come mi hai consigliato. Ma non ho capito come fai a stabilire che i byte che mi danno il dato current_mA è formato da questi caratteri:f3ff...
Però scusa tipo questo dato come fai a decodificarlo: "f3ff5b1a110200003333113d".
Secondo la tua spiegazione i primi 12 caratteri formano i 3 dati in partenza, ossia corrente temperatura tensione... e gli altri valori??
Patrick_M:
è quello che ti ho scritto nel post #1, tu invii 12 bytes e ne ricevi 24???
per cui ti ho detto, se consideri solo i primi 12....
Il problema secondo me è più serio: se lui ritieni di inviare 12 bit, e ne riceve 24 vuol dire che c'è un problema su quello che sta inviando, o che perlomeno non sta inviando esattamente quello che desiderano o che crede. Per questo non credo sia sufficiente semplicemente "tagliare" il messaggio e considerare i primi 12 byte, Ma ritengo sia necessario capire perché ne riceve 24 e risolvere il problema in fondo.
Per fare questo credo che serva un programma semplice di prova il cui unico scopo sia inviare tramite quel metodo down Arduino all'altro dei dati conosciuti e fissi e vedere attraverso monitor seriale direttamente quello che il secondo Arduino riceve.
infatti, io non ho detto di tagliare il messaggio, io ho fatto l'esempio di come deve ritrasformare l'asadecimale per ottenere i valori di partenza come da richiesta
Qualcuno può aiutarmi a decodificarlo?? E spiegarmi come fare...
ed è dalla prima risposta che sostengo che i byte ricevuti sono troppi
che significa scrivere un intero tra -16mila e fischia e +16mila e fischia per correnti che vanno da -60 a +60mA
con che risoluzione? siamo sicuri di dover usare così tanti bit?
ma comunque tralasciamo problemi di misure (che tanto torneranno...)
3) ma la stringa "f3ff591ae10100000000043d" è composta da 24 caratteri, come dice lo OP, ma rappresenta in esadecimale solo 12 byte (come lo OP desidera, in effetti)
quindi si ritorna alla domanda 1: CHI ha ricevuto questa stringa?
che se la dividiamo in 3 gruppi da 8 cifre esadecimali otteniamo
f3ff591a e1010000 0000043d
che a casa mia sono valori validissimi per 3 interi a 32 bit
OPS forse che il problema è li?
la conversione e la struttura di trasmissione parla di 3 interi a 16 bit
ma viene trasmesso un messaggio di 12 byte
SigFox.write((uint8_t*)&msg,12);
ma tre interi da 16 bit fanno 3 per 2 uguale 6 byte, evidentemente i successivi 6 vengono "raspati" su dalla funzione di trasmissione, alla quale viene passato un oggetto lungo 6 byte, ma le viene ordinato di trasmetterne 12
che quando li andiamo a vedere, di nuovo la domanda 1: li vediamo ricevuti e mostrati da cosa?
sembrano 24 perchè rappresentati ognuno con 2 (due) cifre esadecimali
Ora mi sono trovato con il messaggio inviato che dovrebbe essere in forma esadecimale e non riesco a riconvertirlo in formato decimale, cioè ai valori standard leggibili.
Esempio: "f3ff591ae10100000000043d"
I valori che tu hai trasmesso, secondo questo esempio, sono:
Quello che non torna e' che sono tutti al di fuori dei limiti impostati dalla funzione di conversione, e cioe' +-60 per corrente e temperatura e +25 per la tensione.
Normalmente quando si dice "carattere" si intende "byte", quindi : f3ff591ae10100000000043d sono 12 byte, che e' quello che ti devi aspettare perche' chiami la funzione di trasmissione con il parametro di lunghezza = 12
SigFox.write((uint8_t*)&msg,12);
Quello che e' sbagliato, come ti fa notare Standardoil, e' che tu di byte da trasmettere ne hai solo 6, e quindi i primi 6 f3ff591ae101 e' roba buona ma i 6 finali 00000000043d vengono "raspati su", come dice Standardoil.
Quello che non torna e' che sono tutti al di fuori dei limiti impostati dalla funzione di conversione, e cioe' +-60 per corrente e temperatura e +25 per la tensione.
Normalmente quando si dice "carattere" si intende "byte", quindi : f3ff591ae10100000000043d sono 12 byte, che e' quello che ti devi aspettare perche' chiami la funzione di trasmissione con il parametro di lunghezza = 12
Ciao
Marco
ops scusate, in effetti io sostenevo che fossero 24 byte
ma in effetti intendevo che quelli trasmessi erano appunto i primi 6
mea culpa
solo una rettifica:
i valori ottenuti dopo la riconversione in decimale in effetti sono
msg.Current_mA = 0xF3FF = (2 byte) = 220
msg.Temperature = 0x591A = (2 byte) = 83 (che se sono fahrenheit danno 28,3° C)
msg.voltIn = 0xE101 = (2 byte) = 5
che mi paiono valori consoni
edit:
no nella libreria specifica che :
** Retrieve temperature and pressure.
** @param : T = stores the temperature value in degC.
** @param : P = stores the pressure value in mBar.
non sono poi così consoni,
se pensi che i due fondo scala per la corrente sono + e - 60mA, 220 è chiaramente fuori scala
e qui sorge il dubbio relativo alla mia domanda numero 2: perchè riscalare le misure?
ma senza la risposta alla domanda numero 1, è inutile continuare, non si saprebbe in che direzione andare....
non ho idea del motivo per cui siano stati usati quei valori come limiti nel calcolo, mi sa di copia/incolla
e ovviamente non ho neppure idea del perchè venga eseguita questa trasformazione anzichè accodarli uno all'altro tal quali...
cerco un attimo...
trovato
tratto da qui
"Since the Sigfox network can send a maximum of 120 messages per day (depending on your plan)
we'll optimize the readings and send data in compact binary format"
il programmino usato per la conversione è questo
che sarebbero 5 messaggi/ora
ci si fa un'automazione embrionale embrionale, quasi da poveri....
preferisco il mio telegrambot, che dopo averlo ripulito delle vare "porcherie" che ho trovato nelle librerie originali sembra andare molto bene
Sulimarco:
Quello che non torna e' che sono tutti al di fuori dei limiti impostati dalla funzione di conversione, e cioe' +-60 per corrente e temperatura e +25 per la tensione.
Ma scusate, nel codice si vede che di fatto mappa i valori tra min e max riportando questo intervallo al valore di un int. Infatti leggo:
Quindi i mA e temperatura sono convertiti in int signed (-60 = -1 = 0x8000, +60 = 32767 = 0x7FFF) mentre i volt in unsigned (0 V = 0 = 0x0000, 25 V = 65535 = 0xFFFF)
EDIT: verificare solo se i byte sono memorizzati in Little Endian, nel caso le coppie di byte che compongono lo short vanno invertiti, es. E101 diventa in realtà 0x01E1)
che sarebbero 5 messaggi/ora
ci si fa un'automazione embrionale embrionale, quasi da poveri....
Con Sigfox non si fa automazione si fa IOT e cioe':
pochi dati scambiati molto raramente
potenza di trasmissione bassa
dimensione dei sensori molto piccole
durata delle batterie molto lunga
Il motivo di compattare i dati e' che si paga il servizio in funzione del numero di messaggi trasmessi, anche se nell'esempio in questione non ce ne sarebbe bisogno perche' 3 float stanno in un messaggio.
Adesso ho provato ad usare come da voi consigliato sizeof(msg) e mi manda solo più 6byte come corretto.
Stavolta l'output è questo: feffd3191102.
Considerando che la temperatura è data da 0xd319, utilizzando l'algoritmo con la funzione inversa mi restituisce un valore che non sta ne in cielo ne in terra: -42.09...
Perché?
Devo ancora aggiungere sensori, e quindi valori, per questo devo impacchettare tutto in un messaggio.
Grazie a tutti
filippocarastro:
Adesso ho provato ad usare come da voi consigliato sizeof(msg) e mi manda solo più 6byte come corretto.
Stavolta l'output è questo: feffd3191102.
Considerando che la temperatura è data da 0xd319, utilizzando l'algoritmo con la funzione inversa mi restituisce un valore che non sta ne in cielo ne in terra: -42.09...
Perché?
Devo ancora aggiungere sensori, e quindi valori, per questo devo impacchettare tutto in un messaggio.
Grazie a tutti
a me da 20 il tuo algoritmo di partenza era costante= 65535/25 25 è in tuo limite max quindi costante=2621 quindi la codifica è temperaturacostante = temperatura 2621 il valore 0xD319 (preso come unsigned) = 54041 quindi per recuperare il valore originale devi fare codifica / costante =54041 / 2621 = 20
scusa sbagliato
costante = 32767 / 60-(-60)=273
per cui se 0xd319 è signad da -42
se unsigned da 197...
però se il valore va invertito
e cioè0x19d3
il risultato è 24
se tu ti fai stampare i valori di partenza poi sai cosa devi ottenere all'arrivo....