Gateway per BUS Dallas (OneWire)
Schema di principio del BUS OneWire
Notare i collegamenti in parallelo tra tutti i dispositivi attorno a 2 (parasite mode) o 3 fili (normal mode).
Il sensore di temperatura DS18B20
Parasite mode
Il bus onewire teoricamente possiede 2 soli fili (uno senza la massa):
- una massa comune per il ritorno della corrente
- un filo dati che è usato anche per l’alimentazione del dispositivo. Poichè il livello L (basso) è di solito codificato con 0V l’alimentazione risulta intermittente. Per ovviare a questi buchi (lack) di alimentazione si collega una capacità in parallelo a massa e linea dati che funge da tampone locale alla mancanza di alimentazione dovuta a sequenze consecutive di zeri. Questo modo di funzionamente si chiama parasite mode.
Normal mode
In pratica è usuale anche un collegamento a 3 fili (2 senza la massa):
- una massa comune per il ritorno della corrente
- un filo dati che è a se stante cioè non viene usato anche per l’alimentazione del dispositivo.
- un positivo di alimentazione che alimenta tutti i dispositivi. Questa modalità si chiama normal mode.
Librerie del progetto
Dal punto di vista SW sevono due librerie da scaricare e scompattare dentro la solita cartella libraries (disponibili su Git al link https://github.com/PaulStoffregen/OneWire e al link https://github.com/milesburton/Arduino-Temperature-Control-Library) :
- OneWire-master.zip da scompattare e rinominare semplicemente OneWire. Per installare il protocollo standard OneWire.
- Arduino-Temperature-Control-Library-master da scompattare e rinominare semplicemente DallasTemperature per installare il particolare protocollo applicativo di quella categoria di sensori di temperatura (DS18B20).
Gateway OneWire-LoRaWan con modem LMIC
La libreria MQTT è asincrona per cui non bloccante. E’ adoperabile sia per ESP8266 che per ESP32.
Anche in questo caso sono possibili entrambi i collegamenti, normal mode e parasite mode. Di seguito è illustrato il normal mode:
/*******************************************************************************
* Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
* Copyright (c) 2018 Terry Moore, MCCI
*
* Permission is hereby granted, free of charge, to anyone
* obtaining a copy of this document and accompanying files,
* to do whatever they want with them without any restriction,
* including, but not limited to, copying, modification and redistribution.
* NO WARRANTY OF ANY KIND IS PROVIDED.
*
* This example sends a valid LoRaWAN packet with payload "Hello,
* world!", using frequency and encryption settings matching those of
* the The Things Network.
*
* This uses OTAA (Over-the-air activation), where where a DevEUI and
* application key is configured, which are used in an over-the-air
* activation procedure where a DevAddr and session keys are
* assigned/generated for use with all further communication.
*
* Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
* g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
* violated by this sketch when left running for longer)!
* To use this sketch, first register your application and device with
* the things network, to set or generate an AppEUI, DevEUI and AppKey.
* Multiple devices can use the same AppEUI, but each device has its own
* DevEUI and AppKey.
*
* Do not forget to define the radio type correctly in
* arduino-lmic/project_config/lmic_project_config.h or from your BOARDS.txt.
*
*******************************************************************************/
#define ARDUINO_HELTEC_WIRELESS_STICK 1
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
// include the DS18B20 Sensor Library
#include <OneWire.h>
#include <DallasTemperature.h>
//sensors defines
#define ONEWIREPORT 1
#define RADIO_MOSI_PORT 27
#define RADIO_MISO_PORT 19
#define RADIO_SCLK_PORT 5
#define RADIO_NSS_PORT 18
//
// For normal use, we require that you edit the sketch to replace FILLMEIN
// with values assigned by the TTN console. However, for regression tests,
// we want to be able to compile these scripts. The regression tests define
// COMPILE_REGRESSION_TEST, and in that case we define FILLMEIN to a non-
// working but innocuous value.
//
#define FILLMEIN 1
/*
#ifdef COMPILE_REGRESSION_TEST
#define FILLMEIN 0
#else
#warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!"
#define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN)
#endif
*/
// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={ FILLMEIN };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]={ FILLMEIN };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
static const u1_t PROGMEM APPKEY[16] = { FILLMEIN };
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
// payload to send to TTN gateway
static uint8_t payload[5];
static osjob_t sendjob;
bool flag_TXCOMPLETE = false;
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 5;
// Declared in hal.h, to be defined and initialized by the application.
// Use os_init_ex() if you want not to use a const table, or if
// you need to define a derived type (so you can override methods).
//extern const lmic_pinmap lmic_pins;
// Pin mapping for Heltec ESP32 and Wireless Stick Lite
const lmic_pinmap lmic_pins = { // deve avere questo nome se globale!
.nss = 18, //CS pin
.rxtx = LMIC_UNUSED_PIN,
.rst = 14, //RST PIN
.dio = {26, 35, 34}, //DIO 0, 1, 2
//.mosi = 27,
//.miso = 19,
//.sck = 5,
};
//const lmic_pinmap *pPinMap = Arduino_LMIC::GetPinmap_ThisBoard();
// Setup the one wire connection on pin 10
OneWire oneWire(ONEWIREPORT);
DallasTemperature sensors(&oneWire);
DeviceAddress thermometer;
void printHex2(unsigned v) {
v &= 0xff;
if (v < 16)
Serial.print('0');
Serial.print(v, HEX);
}
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch(ev) {
case EV_JOINED:
Serial.println(F("EV_JOINED"));
{
u4_t netid = 0;
devaddr_t devaddr = 0;
u1_t nwkKey[16];
u1_t artKey[16];
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
Serial.print("netid: ");
Serial.println(netid, DEC);
Serial.print("devaddr: ");
Serial.println(devaddr, HEX);
Serial.print("AppSKey: ");
for (size_t i=0; i<sizeof(artKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(artKey[i]);
}
Serial.println("");
Serial.print("NwkSKey: ");
for (size_t i=0; i<sizeof(nwkKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(nwkKey[i]);
}
Serial.println();
}
// Disable link check validation (automatically enabled
// during join, but because slow data rates change max TX
// size, we don't use it in this example.
LMIC_setLinkCheckMode(0);
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.print(F("Received "));
Serial.print(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
flag_TXCOMPLETE = true;
break;
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println(F("EV_TXCANCELED"));
break;
case EV_RXSTART:
/* do not print anything -- it wrecks timing */
break;
case EV_JOIN_TXCOMPLETE:
Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
break;
default:
Serial.print(F("Unknown event: "));
Serial.println((unsigned) ev);
break;
}
}
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Get the temp
sensors.getAddress(thermometer, 0);
sensors.setResolution(thermometer, 12);
sensors.requestTemperatures();
uint16_t temperature = sensors.getTempC(thermometer);
// Split both words (16 bits) into 2 bytes of 8
byte payload[2];
payload[0] = highByte(temperature);
payload[1] = lowByte(temperature);
Serial.print("Temperature: ");
Serial.println(temperature);
// prepare upstream data transmission at the next possible time.
// transmit on port 1 (the first parameter); you can use any value from 1 to 223 (others are reserved).
// don't request an ack (the last parameter, if not zero, requests an ack from the network).
// Remember, acks consume a lot of network resources; don't ask for an ack unless you really need it.
LMIC_setTxData2(1, payload, sizeof(payload)-1, 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
void initLoRaWAN() {
Serial.println(F("LoraWan init"));
// LMIC init using the computed target
//const lmic_pinmap *lmic_pins = Arduino_LMIC::GetPinmap_ThisBoard();
// don't die mysteriously; die noisily.
//os_init_ex((const void *)&lmic_pins);
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// by joining the network, precomputed session parameters are be provided.
//LMIC_setSession(0x1, DevAddr, (uint8_t*)NwkSkey, (uint8_t*)AppSkey);
// Enabled data rate adaptation
LMIC_setAdrMode(1);
// Enable link check validation
LMIC_setLinkCheckMode(0);
// Set data rate and transmit power
LMIC_setDrTxpow(DR_SF7, 21);
LMIC_selectSubBand(1);
}
void sensorInit(){
Serial.println(F("Dallas init"));
sensors.begin();
}
void setup() {
Serial.begin(115200);
delay(10000);
Serial.println(F("ESP Starting"));
#ifdef VCC_ENABLE
// For Pinoccio Scout boards
pinMode(VCC_ENABLE, OUTPUT);
digitalWrite(VCC_ENABLE, HIGH);
delay(1000);
#endif
sensorInit();
// Setup LoRaWAN state
initLoRaWAN();
//sensorInit();
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
}
void loop() {
os_runloop_once();
/* In caso di instabilit�
//Run LMIC loop until he as finish
while(flag_TXCOMPLETE == false)
{
os_runloop_once();
}
flag_TXCOMPLETE = false;
*/
}
Sitografia:
https://randomnerdtutorials.com/esp32-mqtt-publish-ds18b20-temperature-arduino/ https://randomnerdtutorials.com/micropython-mqtt-publish-ds18b10-esp32-esp8266/ https://randomnerdtutorials.com/esp32-ds18b20-temperature-arduino-ide/ https://randomnerdtutorials.com/esp32-multiple-ds18b20-temperature-sensors/