I am working on a project involving 2 ESP32 Wemos D1 Mini boards. I am using the BLE feature to transmit a sensor reading from the "server" to the "client". I use a Characteristic Notify to the client which receives the sensor reading. If I want to implement deep sleep functionality to the server, what would happen to the client? Does the client also have to reset at some point?
Also, is it advisable to use Characteristic.Notify in a deep sleep scenario?
Thanks.
Server code:
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT22
#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 15 //Time ESP32 will go to sleep (in seconds)
RTC_DATA_ATTR int bootCount = 0;
DHT dht(DHTPIN, DHTTYPE);
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 50;
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
//Function that prints the reason by which ESP32 has been awaken from sleep
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case 1 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 2 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 3 : Serial.println("Wakeup caused by timer"); break;
case 4 : Serial.println("Wakeup caused by touchpad"); break;
case 5 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
void setup() {
Serial.begin(115200);
Serial.println(F("initating DHT22..."));
dht.begin();
// Create the BLE Device
BLEDevice::init("UART"); // Name must not be longer than 5 chars!!!
// Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY|BLECharacteristic::PROPERTY_READ|BLECharacteristic::PROPERTY_WRITE
);
BLE2902 *desc = new BLE2902();
desc->setNotifications(true);
pCharacteristic->addDescriptor(desc);
// Start the service
pService->start();
pServer->getAdvertising()->addServiceUUID(SERVICE_UUID);
// Start advertising
pServer->getAdvertising()->start();
Serial.println(pService->getUUID().toString().c_str());
Serial.println("Waiting a client connection to notify...");
if (deviceConnected) {
float f = dht.readTemperature(true);
char fStr[10];
sprintf(fStr, "%4.4f", f);
Serial.print("Temperature reading: ");
Serial.println(fStr);
Serial.printf("*** Sent Value: %d ***\n", fStr);
pCharacteristic->setValue(fStr);
pCharacteristic->notify();
//Set timer to 5 seconds
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
" Seconds");
//Go to sleep now
esp_deep_sleep_start();
}
//delay(60000);
}
void loop() {}
Client code:
#include "BLEDevice.h"
#include <WiFi.h>
// The remote service we wish to connect to.
static BLEUUID serviceUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
static BLEUUID charUUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
static BLEAddress *pServerAddress;
static boolean doConnect = false;
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
const char* ssid = "Kings";
const char* password = "GoCanada";
const char* host = "menezes-service.herokuapp.com";
WiFiClient client;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
//std::string value = pBLERemoteCharacteristic->readValue();
byte buffer[42];
Serial.print("The characteristic value sent was: ");
//Serial.println(pBLERemoteCharacteristic->readValue().c_str());
//Serial.println(pBLERemoteCharacteristic->readUInt8());
std::string farhenheight = pRemoteCharacteristic->readValue();
Serial.print("Farheinheight: ");
Serial.println(farhenheight.c_str());
Serial.println(F("Posting to api!"));
Serial.println();
Serial.println("closing connection");
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
Serial.println("connected again ... ");
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer(BLEAddress pAddress) {
Serial.print("Forming a connection to ");
Serial.println(pAddress.toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(pAddress);
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
Serial.println(pRemoteService->toString().c_str());
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
return false;
}
Serial.println(" - Found our characteristic");
pRemoteCharacteristic->registerForNotify(notifyCallback);
}
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
//Serial.print(advertisedDevice.haveServiceUUID());
if(advertisedDevice.haveServiceUUID()){
Serial.println(advertisedDevice.getServiceUUID().toString().c_str());
}
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {
//
Serial.print("Found our device! address: ");
advertisedDevice.getScan()->stop();
pServerAddress = new BLEAddress(advertisedDevice.getAddress());
doConnect = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(30);
} // End of setup.
// This is the Arduino main loop function.
void loop() {
if (doConnect == true) {
if (connectToServer(*pServerAddress)) {
Serial.println("We are now connected to the BLE Server.");
connected = true;
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
//doConnect = false;
}
if (connected == false){
BLEDevice::getScan()->start(0);
}
else{
doConnect = false;
}
delay(1000); // Delay a second between loops.
} // End of loop
Please see answers to your questions below:-
If I want to implement deep sleep functionality to the server, what would happen to the client? Does the client also have to reset at some point?
No the client does not have to reset, but you may have to reconnect to the server because in deep sleep the BLE connection is lost. If you want the connection to be established automatically as soon as the server wakes up, then you have to update the client code so that it continuously attempts to reconnect to the server. This way, as soon as the server wakes up, the client would connect to it and continue receiving notifications.
Also, is it advisable to use Characteristic.Notify in a deep sleep scenario?
In deep sleep the CPU will be off, therefore you will not be able to send notifications in this state. In this mode you will only be able to wake up the CPU through a timer or an external peripheral (e.g. touch pins). Please see the link below for more information:-
https://lastminuteengineers.com/esp32-deep-sleep-wakeup-sources/
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html
https://randomnerdtutorials.com/esp32-deep-sleep-arduino-ide-wake-up-sources/
I hope this helps.
Related
I have connected an ESP32 LoRa to a moisture sensor. I have a script for reading data from the sensor, which works perfectly fine on its own:
#define SensorPin 27
float sensorValue = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(analogRead(SensorPin));
delay(1000);
}
It returns about 1800-2000 when it is in some dirt.
I then want to send the data to another ESP32 LoRa, where i have used this tutorial: https://randomnerdtutorials.com/esp-now-two-way-communication-esp32/
It works fine in terms of sending data between the ESPs, but now my sensor constantly returns 0, which is super weird.
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
#define SensorPin 27
float sensorValue = 0;
// REPLACE WITH THE MAC Address of your receiver
uint8_t broadcastAddress[] = {0xA8, 0x03, 0x2A, 0xF3, 0x27, 0x88};
// Define variables to store BME280 readings to be sent
float temperature;
// Define variables to store incoming readings
float incomingTemp;
// Variable to store if sending data was successful
String success;
//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
float temp;
} struct_message;
// Create a struct_message called BME280Readings to hold sensor readings
struct_message BME280Readings;
// Create a struct_message to hold incoming sensor readings
struct_message incomingReadings;
esp_now_peer_info_t peerInfo;
// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
if (status ==0){
success = "Delivery Success :)";
}
else{
success = "Delivery Fail :(";
}
}
// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
Serial.print("Bytes received: ");
Serial.println(len);
incomingTemp = incomingReadings.temp;
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
// Register for a callback function that will be called when data is received
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
Serial.println("Sensor readings:");
getReadings();
// Set values to send
BME280Readings.temp = analogRead(SensorPin); // This returned 1800-2000 before, now it returns 0
// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &BME280Readings, sizeof(BME280Readings));
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
//updateDisplay();
delay(5000);
}
void getReadings(){
temperature = analogRead(SensorPin);
}
void updateDisplay(){ // currently not using this method because I do not care about getting data from the other ESP right now.
// Display Readings in Serial Monitor
Serial.println("INCOMING READINGS");
Serial.print("Temperature: ");
Serial.print(incomingReadings.temp);
Serial.println(" ºC");
}
When using WiFi - you can't use the ADC2 pins for analog input. I've seen the same issue. Here's a link showing a discussion on the ESP32 github pages.
Switch your sensor to one of the ADC1 pins and it should work.
I tried connecting the Arduino MKR NBIoT 1500 board to the Azure IoT Hub but wasn't successful. The board was able to connect to the cellular network and I tried to connect to Azure IoT Hub using MQTT but getting an error “-2”. I have also tried Google IoT and AWS IoT core and I'm still having the same error. I would appreciate if anyone could give me a feedback on what to do to be able to solve the problem. Thank you
Azure IoT Hub NB
This sketch securely connects to an Azure IoT Hub using MQTT over NB IoT/LTE Cat M1.
It uses a private key stored in the ATECC508A and a self signed public
certificate for SSL/TLS authetication.
It publishes a message every 5 seconds to "devices/{deviceId}/messages/events/" topic
and subscribes to messages on the "devices/{deviceId}/messages/devicebound/#"
topic.
The circuit:
- MKR NB 1500 board
- Antenna
- SIM card with a data plan
- LiPo battery
The following tutorial on Arduino Project Hub can be used
to setup your Azure account and the MKR board:
https://create.arduino.cc/projecthub/Arduino_Genuino/securely-connecting-an-arduino-nb-1500-to-azure-iot-hub-af6470
This example code is in the public domain.
*/
#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include <utility/ECCX08SelfSignedCert.h>
#include <ArduinoMqttClient.h>
#include <MKRNB.h>
#include "arduino_secrets.h"
/////// Enter your sensitive data in arduino_secrets.h
const char pinnumber[] = SECRET_PINNUMBER;
const char broker[] = SECRET_BROKER;
String deviceId = SECRET_DEVICE_ID;
NB nbAccess=true;
GPRS gprs;
NBClient nbClient; // Used for the TCP socket connection
BearSSLClient sslClient(nbClient); // Used for SSL/TLS connection, integrates with ECC508
MqttClient mqttClient(sslClient);
unsigned long lastMillis = 0;
void setup() {
Serial.begin(9600);
while (!Serial);
if (!ECCX08.begin()) {
Serial.println("No ECCX08 present!");
while (1);
}
// reconstruct the self signed cert
ECCX08SelfSignedCert.beginReconstruction(0, 8);
ECCX08SelfSignedCert.setCommonName(ECCX08.serialNumber());
ECCX08SelfSignedCert.endReconstruction();
// Set a callback to get the current time
// used to validate the servers certificate
ArduinoBearSSL.onGetTime(getTime);
// Set the ECCX08 slot to use for the private key
// and the accompanying public certificate for it
sslClient.setEccSlot(0, ECCX08SelfSignedCert.bytes(), ECCX08SelfSignedCert.length());
// Set the client id used for MQTT as the device id
mqttClient.setId(deviceId);
// Set the username to "<broker>/<device id>/api-version=2018-06-30" and empty password
String username;
username += broker;
username += "/";
username += deviceId;
username += "/api-version=2018-06-30";
mqttClient.setUsernamePassword(username, "");
// Set the message callback, this function is
// called when the MQTTClient receives a message
mqttClient.onMessage(onMessageReceived);
}
void loop() {
if (nbAccess.status() != NB_READY || gprs.status() != GPRS_READY) {
connectNB();
}
if (!mqttClient.connected()) {
// MQTT client is disconnected, connect
connectMQTT();
}
// poll for new MQTT messages and send keep alives
mqttClient.poll();
// publish a message roughly every 5 seconds.
if (millis() - lastMillis > 5000) {
lastMillis = millis();
publishMessage();
}
}
unsigned long getTime() {
// get the current time from the cellular module
return nbAccess.getTime();
//return 1583929365;
}
void connectNB() {
Serial.println("Attempting to connect to the cellular network");
while ((nbAccess.begin(pinnumber) != NB_READY) ||
(gprs.attachGPRS() != GPRS_READY)) {
// failed, retry
Serial.print(".");
delay(1000);
}
Serial.println("You're connected to the cellular network");
Serial.println();
}
void connectMQTT() {
Serial.print("Attempting to MQTT broker: ");
Serial.print(broker);
Serial.println(" ");
while (!mqttClient.connect(broker, 8883)) {
// failed, retry
Serial.print(".");
Serial.println(mqttClient.connectError());
delay(5000);
}
Serial.println();
Serial.println("You're connected to the MQTT broker");
Serial.println();
// subscribe to a topic
mqttClient.subscribe("devices/" + deviceId + "/messages/devicebound/#");
}
void publishMessage() {
Serial.println("Publishing message");
// send message, the Print interface can be used to set the message contents
mqttClient.beginMessage("devices/" + deviceId + "/messages/events/");
mqttClient.print("hello ");
mqttClient.print(millis());
mqttClient.endMessage();
}
void onMessageReceived(int messageSize) {
// we received a message, print out the topic and contents
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");
// use the Stream interface to print the contents
while (mqttClient.available()) {
Serial.print((char)mqttClient.read());
}
Serial.println();
Serial.println();
}
// NB settings
#define SECRET_PINNUMBER ""
// Fill in the hostname of your Azure IoT Hub broker
#define SECRET_BROKER "ArduinoProjectHub.azure-devices.net"
// Fill in the device id
#define SECRET_DEVICE_ID "MKRNB1500"
I'm trying to let my Arduino and esp8266 send data to thingsboard and then subscribe to thingsboard's mqtt channel and get a timestamp from it but for some unknown reason, it just doesn't work. Checked server-side and it was ok, tried postman to simulate request and also getting the correct response from the server.
Also, I had read the documentation about esp8266 and it somehow did state that it only can have 1 connection simultaneously. But tried to let my Arduino to only subscribe to channel but it still doesn't work.
My code:(I'm using Arduino Mega for this)
#include "DHT.h"
#include <WiFiEspClient.h>
#include <WiFiEsp.h>
#include <WiFiEspUdp.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <TimeLib.h>
#define WIFI_AP "CEC"
#define WIFI_PASSWORD "#CEC#2017#CEC#"
#define TOKEN "A1_TEST_TOKEN"
// DHT
#define DHTPIN 2
#define DHTTYPE DHT22
char thingsboardServer[] = "192.168.0.250";
// Initialize the Ethernet client object
WiFiEspClient espClient;
// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);
PubSubClient client(espClient);
int status = WL_IDLE_STATUS;
unsigned long lastSend;
unsigned long lastSync;
void setup() {
// initialize serial for debugging
Serial.begin(9600);
Serial1.begin(9600);
Serial2.begin(9600);
//serial pin
pinMode(LED_RUN_pin, OUTPUT);
//dht.begin();
InitWiFi();
lastSend = 0;
lastSync = 0;
//client subscribe thingsboard rpc PUBLISH msg
client.setServer( thingsboardServer, 1883 );
client.setCallback(on_message);
}
void loop() {
status = WiFi.status();
if ( status != WL_CONNECTED) {
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(WIFI_AP);
// Connect to WPA/WPA2 network
status = WiFi.begin(WIFI_AP, WIFI_PASSWORD);
delay(500);
}
}
if ( !client.connected() ) {
reconnect();
}
if ( millis() - lastSend > 30000 ) { // Update and send after 30 seconds
getAndSendTemperatureAndHumidityData();
lastSend = millis();
}
client.loop();
}
void getAndSendTemperatureAndHumidityData()
{
Serial.println("Collecting temperature data.");
// Reading temperature or humidity takes about 250 milliseconds!
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
Serial.print("Humidity: ");
Serial.print(h);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(t);
Serial.print(" *C ");
String temperature = String(t);
String humidity = String(h);
// Prepare a JSON payload string
String payload = "{";
payload += "\"temperature\":"; payload += temperature; payload += ",";
payload += "\"humidity\":"; payload += humidity;
payload += "}";
// Send payload
char attributes[100];
payload.toCharArray( attributes, 100 );
client.publish( "v1/devices/me/rpc/request/1", attributes , 1);
//Serial.println( attributes );
}
// Prepare a JSON payload string
String payload = "{method: getTime, params:{}}";
// Send payload
char attributes[100];
payload.toCharArray( attributes, 100 );
client.publish( "v1/A1_TEST_TOKEN/rpc", attributes );
//Serial.println( attributes );
}
void InitWiFi()
{
// initialize serial for ESP module
Serial1.begin(9600);
// initialize ESP module
WiFi.init(&Serial1);
// check for the presence of the shield
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue
while (false);
}
Serial.println("Connecting to AP ...");
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
// Connect to WPA/WPA2 network
status = WiFi.begin(WIFI_AP, WIFI_PASSWORD);
delay(500);
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
//Serial.print("Connecting to Thingsboard node ...");
// Attempt to connect (clientId, username, password)
if ( client.connect("Arduino Uno Device", TOKEN, NULL) ) {
Serial.println( "[DONE]" );
delay(500);
// Serial.println("Subscribing RPC");
client.subscribe("v1/devices/me/rpc/request/+");
} else {
Serial.print( "[FAILED] [ rc = " );
Serial.print( client.state() );
Serial.println( " : retrying in 20 seconds]" );
// Wait 20 seconds before retrying
delay( 20000 );
}
}
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
// The callback for when a PUBLISH message is received from the server.
void on_message (char* topic, byte* payload, unsigned int length) {
//Serial.println("On message");
char json[length + 1];
strncpy (json, (char*)payload, length);
json[length] = '\23';
Serial.print("Topic: ");
Serial.println(topic);
Serial.print("Message: ");
Serial.println(json);
// Decode JSON request
StaticJsonBuffer<200> jsonBuffer;
JsonObject& data = jsonBuffer.parseObject((char*)json);
if (!data.success())
{
Serial.println("parseObject() failed");
return;
}
}
Probably a stupid remark, but is your TOKEN a valid Thingsboard device token? I assume you entered the value A1_TEST_TOKEN to hide your real authentication token.
I also assume you are trying to send sensor data (telemetry) to Thingsboard. Why did you decide to use the RPC API for sending data? I think it might be easier to use the MQTT Device API instead.
I don't have any experience in developing for Arduino. I am using Thingsboard together with a Raspberry PI to write and display sensor data. Hope you find a solution for your problem!
I have programmed to my ESP8266 and subscribed one topic to keep listening messages. This is my graphical view of injecting message to IBM Iot node.
This is my settings of inject view
This is my settings of IBM Iot node.
Here are my logs at Serial Monitor, it is connected and subscribed to cmd channel
So far so good, When I am trying to inject a message to my IBM Iot node then it is not publishing a message, as it is not reaching on serial monitor and no log on debug view. here you can see
Here is source code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h> // https://github.com/knolleary/pubsubclient/releases/tag/v2.3
const char* ssid = "shiv";
const char* password = "manmohan#12345";
#define ORG "2kafk4"
#define DEVICE_TYPE "ESP8266"
#define DEVICE_ID "5CCF7FEED6F0"
#define TOKEN "opKF7v3#8jRM*mGkb_"
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
char topic[] = "iot-2/cmd/test/fmt/String";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
WiFiClient wifiClient;
void callback(char* topic, byte* payload, unsigned int payloadLength) {
Serial.print("callback invoked for topic: "); Serial.println(topic);
for (int i = 0; i < payloadLength; i++) {
Serial.print((char)payload[i]);
}
}
PubSubClient client(server, 1883, callback, wifiClient);
void setup() {
Serial.begin(115200);
Serial.println();
wifiConnect();
mqttConnect();
}
void loop() {
if (!client.loop()) {
mqttConnect();
}
}
void wifiConnect() {
Serial.print("Connecting to "); Serial.print(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("nWiFi connected, IP address: "); Serial.println(WiFi.localIP());
}
void mqttConnect() {
if (!client.connected()) {
Serial.print("Reconnecting MQTT client to "); Serial.println(server);
while (!client.connect(clientId, authMethod, token)) {
Serial.print(".");
delay(500);
}
initManagedDevice();
Serial.println();
}
}
void initManagedDevice() {
if (client.subscribe(topic)) {
Serial.println("subscribe to cmd OK");
} else {
Serial.println("subscribe to cmd FAILED");
}
}
I tried to check cloud foundry logs using cf command, here it is https://pastebin.com/dfMaS1Gd
Can anyone hint me what I am doing wrong ? Thanks in advance.
Confirm the device type is correctly specified in your node configuration. Currently the screenshot show 0.16.2 which doesn't seem to match the device type you registered and what is specified in your code.
I'm trying to connect a DHT22 sensor to the Pachube online service.
I am understanding the code and have everything wired up correctly but I get this error:
DHT22 Library Demo
Requesting data at 6335
Sync Timeout
What does sync timeout mean? Is is a network problem?
How could I fix this?
Here is my code anyway:
/* Feed temperature and humidity to Pachube.
Based on the following examples:
Sample code from nethoncho's DHT22 library:
https://github.com/nethoncho/Arduino-DHT22
Tom Igoe's PachubeClient:
http://arduino.cc/en/Tutorial/PachubeCient
*/
#include <DHT22.h>
#include <SPI.h>
#include <Ethernet.h>
// Data wire is plugged into port 7 on the Arduino
// Connect a 4.7K resistor between VCC and the data pin (strong pullup)
#define DHT22_PIN 2
// Setup a DHT22 instance
DHT22 myDHT22(DHT22_PIN);
static unsigned long lWaitMillis;
// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
byte ip[] = {
192,168,0,30 };
byte gateway[] = {
192,168,1,2};
byte subnet[] = {
255, 255, 255, 0 };
// The address of the server you want to connect to (pachube.com):
byte server[] = {
173,203,98,29 };
// initialize the library instance:
Client client(server, 80);
boolean lastConnected = false; // state of the connection last time through the main loop
const long postingInterval = 180000; //delay between updates to Pachube.com
int backoff = 0;
void setup(void)
{
// start serial port
Serial.begin(9600);
Serial.println("DHT22 Library Demo");
// start the ethernet connection:
Ethernet.begin(mac, ip);
// give the ethernet module time to boot up:
delay(1000);
lWaitMillis = millis() + 5000;
}
void loop() {
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}
// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
while(client.status() != 0) {
Serial.print("Client status: ");
Serial.println(client.status());
delay(5);
}
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (long)( millis() - lWaitMillis ) >= 0 ) {
if (readData()) {
int temp = myDHT22.getTemperatureC();
int humidity = myDHT22.getHumidity() + .5;
sendData(temp, humidity);
}
lWaitMillis += postingInterval;
if (lWaitMillis < millis()) {
lWaitMillis = millis() + postingInterval;
}
Serial.print("Next attempt at ");
Serial.println(lWaitMillis);
Serial.println();
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
boolean readData()
{
DHT22_ERROR_t errorCode;
Serial.print("Requesting data at ");
Serial.println(millis());
errorCode = myDHT22.readData();
switch(errorCode)
{
case DHT_ERROR_NONE:
Serial.print("Got Data ");
Serial.print(myDHT22.getTemperatureC());
Serial.print("C ");
Serial.print(myDHT22.getHumidity());
Serial.println("%");
return true;
break;
case DHT_ERROR_CHECKSUM:
Serial.print("check sum error ");
Serial.print(myDHT22.getTemperatureC());
Serial.print("C ");
Serial.print(myDHT22.getHumidity());
Serial.println("%");
break;
case DHT_BUS_HUNG:
Serial.println("BUS Hung ");
break;
case DHT_ERROR_NOT_PRESENT:
Serial.println("Not Present ");
break;
case DHT_ERROR_ACK_TOO_LONG:
Serial.println("ACK time out ");
break;
case DHT_ERROR_SYNC_TIMEOUT:
Serial.println("Sync Timeout ");
break;
case DHT_ERROR_DATA_TIMEOUT:
Serial.println("Data Timeout ");
break;
case DHT_ERROR_TOOQUICK:
Serial.println("Polled too quick ");
break;
}
return false;
}
// this method makes a HTTP connection to the server:
void sendData(int temp, int humidity) {
// if there's a successful connection:
if (client.connect()) {
backoff = 0;
Serial.println("connecting...");
// send the HTTP PUT request.
// fill in your feed address here:
client.print("PUT /v2/feeds/36800.csv HTTP/1.1\n");
client.print("Host: api.pachube.com\n");
// fill in your Pachube API key here:
client.print("X-PachubeApiKey: a6714b6a217827edadfd003843c03c259a08add554eda3871b844612eddc6819\n");
client.print("Content-Length: ");
// calculate the length of the sensor reading in bytes:
int thisLength = 2 + getLength(temp) + 2 + 2 + getLength(humidity);
client.println(thisLength, DEC);
// last pieces of the HTTP PUT request:
client.print("Content-Type: text/csv\n");
client.println("Connection: close\n");
// here's the actual content of the PUT request:
client.print(0, DEC);
client.print(",");
client.println(temp, DEC);
client.print(1, DEC);
client.print(",");
client.println(humidity, DEC);
}
else {
// if you couldn't make a connection:
Serial.println("connection failed, resetting.");
Ethernet.begin(mac, ip);
delay(1000);
client.stop();
delay(1000);
}
}
// This method calculates the number of digits in the
// sensor reading. Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:
int getLength(int someValue) {
// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;
}
// return the number of digits:
return digits;
}
You're running into DHT_ERROR_SYNC_TIMEOUT sensor error, that means that the DHT sensor is running into some sync problem, I guess.
What arduino are you using? Is your board's frequence 8 or 16Mhz?
Give a try to the edit described here, too. If it still doesn't work, I would try using sensor itself (i.e. without connecting to patchube) with some test sketch you can easily find for DHT22, just to make sure the sensor is working properly.
I had similar problem when using Arduino Nano v3.0 + ENC28J60 Ethernet shield. I tried to connect RF receiver to digital PIN #2 but this never worked.
Then I used different pin for the RF module (PIN #4 in my case) and everything worked fine.