Conversion to Arduino MQTT


#1

I have recently converted my Arduino Cayenne project over to Arduino MQTT as I understand that Arduino CAyenne will be closed down soon (Arduino Mega + W5100).
All went OK with conversion but I have some issues with the result:

The ap on the iphone almost always shows as offline for this MQTT project (project name in dull grey rather than bold) even though the icons/actuators etc work OK. Also when I rearrange the icons on the iphone ap dashboard - they do not stay that way next time I open the ap.
This makes the ap quite annoying to use and was working fine under Arduino Cayenne!

I found that I could not populate the dashboard myself with widgets that took their input from the Arduino. Actually I could do it but they did not work properly. When I deleted them and let the dashboard populate itself as data was published - then the icons produced worked fine and could be modified - however the presentation is not very good i.e. When a 2 state icon is OFF it is still coloured (it used to be dull grey) with a 0 beside it, when ON it is coloured with a 1 beside it. It was much better under Arduino Cayenne where it was more obvious when an icon was showing an ON or OFF state.

I have yet to try the triggers to send an SMS for a change of state but hopefully that will work as always. If anyone can help with the above issues it would be greatly appreciated!
Craig


#2

Dear Gentlemen at Cayenne,

I have similar problems. My device is a WeMos D1 Mini, based on ESP8266. It was working 90% well via the Arduino option.
I have converted my code to be MQTT compatible according to your guide, but I have experienced the following issues:

  • After a power or connection fail the Cayenne does not remember and does not restore the previous status of the actuators, it starts every actuators from off ( not like the old Arduino option).
  • The new MQTT solution does nor remember the actuators status at all. If I switch on the motors/lamps and log off, than log on a bit later, it shows all actuators “off” or whatever status (sometimes on, even its real status is off).
  • I have observed, that the Cayenne dashboard does not reacts on / process the messages come from my device.
  • I have tried to remove my device and add again, but now I Cayenne can not see the connected device at all, it says “Waiting for board to connect…”, although the debug messages say “Connection ok”. It is really annoying, I do not / cannot understand what has happened, what did I wrong?

I look forward to your kind reply and help!

BR,
Zoltan


#3

I think that when my code published digital ON/OFF to the dashboard the widget that was automatically set up is an analog sensor - I want it to be simply a 2 state display.
How would I change that? It does not seem possible in the settings of the widget and as I said earlier in my post - when I built the widget myself and let the Arduino code publish to it, it didn’t work properly (widget HIGH all the time regardless of the published value).
Craig


#4

this line should add a 2 state display widget where x is the input value(1 or 0)

 Cayenne.virtualWrite(1, x, "digital_sensor", "d");

#5

Ahhh I see - I was sending the data as analog! The issue with the 2 state display is fixed now thank you.
Still have an issue with the phone ap icons not staying where I put them. And the project appears as though it is offline on the phone ap (light grey) - but still works.
Cheers,
Craig


#6

Ohh and also I don’t seem to be able to set up a trigger to SMS me when my project is offline. Other triggers relating to state of 2 state icons on the dashboard set up fine (yet to check that they work). The online/offline trigger will not save.
Craig


#7

These issues should be fixed when the retain flag is enabled on the Cayenne MQTT server. Tagging @rsiegel

It’s interesting that the board says connected. Did you update the MQTT credentials on the board after re-adding it? Every time you generate a new MQTT device it makes new credentials for that device.

I think that’s just how it shows up, I don;t think it really changes colors based on online/offline. I agree it would be nice to have it like the other devices to easily tell which ones are connected.\

Online/offline triggers currently do not work for MQTT or LoRa devices. As far as I know this is on the road map to add.


#8

Dear adam,
It has not been offered new credentials to me, but it could be a problem on my browser’s side. Currently I am happy with Cayenne, I could been add a new device and it works well.
The only function I could not realize properly the “push button”. Here I quote the whole code I have made and I hope you may suggest some solution or workaround (or just suggests to open a new topic :slight_smile:) /Sorry for the weirdly formatted text!/
Zoltan

//Home IoT solution with Wemos D1 Mini ver 2.2 

//#define CAYENNE_DEBUG
//#define CAYENNE_PRINT Serial
#include <CayenneMQTTESP8266.h>
#include <Adafruit_BME280.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <PCF8574.h>

//Port extender addresses
PCF8574 PCF_01(0x20); //For the outputs/relays
PCF8574 PCF_02(0x27); //For the inputs (0/1)

// My DS18B20's addresses
// 0x28, 0xA0, 0x63, 0x23, 0x07, 0x00, 0x00, 0x9F //1. temperature sensor
// 0x28, 0xFF, 0xD1, 0x5C, 0x52, 0x15, 0x01, 0x68
// 0x28, 0xDA, 0xED, 0x23, 0x07, 0x00, 0x00, 0xA1 //2. temperature sensor
// 0x28, 0x8B, 0xC6, 0x23, 0x07, 0x00, 0x00, 0x30
// 0x28, 0xFF, 0x92, 0xF5, 0x44, 0x16, 0x03, 0x87
// 0x28, 0x90, 0x97, 0x23, 0x07, 0x00, 0x00, 0xCB
// 0x28, 0xCD, 0x8D, 0x23, 0x07, 0x00, 0x00, 0x6E
// 0x28, 0xFF, 0x84, 0x28, 0x65, 0x15, 0x01, 0x2D
DeviceAddress gtemp1 = { 0x28, 0xA0, 0x63, 0x23, 0x07, 0x00, 0x00, 0x9F }; //1.
DeviceAddress gtemp2 = { 0x28, 0xDA, 0xED, 0x23, 0x07, 0x00, 0x00, 0xA1 }; //2.
OneWire oneWire(D5); //Ezeken a lábakon megy: 8, 9 - NEM MEGY 12-en, LEFAGY a 10,11 és 13 esetén
DallasTemperature sensors(&oneWire);

// WiFi and MQTT credentials
char ssid[] = "";
char wifiPassword[] = "";
char username[] = "";
char password[] = "";
char clientID[] = "";

unsigned long lastMillis = 0;
unsigned long lastMillis2 = 0;
unsigned long lastMillis3 = 0;

int S0 = 0;
int S0e = 0;
int S1 = 0;
int S1e = 0;
int S2 = 0;
int S2e = 0;
int S3 = 0;
int S3e = 0;
int S4 = 0;
int S4e = 0;
int S5 = 0;
int S5e = 0;
int S6 = 0;
int S6e = 0;
int S7 = 0;
int S7e = 0;

//BMP280 setup, create instance
Adafruit_BME280 bme;

void setup() {
//  pinMode(D4, OUTPUT);
  pinMode(D5,  INPUT_PULLUP); //One Wire bus pullup to avoid using any external resistor.
	Serial.begin(9600);
	Cayenne.begin(username, password, clientID, ssid, wifiPassword);
  bme.begin();
  sensors.begin();

//Set the DS18B20 resolution to 12 bit
  sensors.setResolution(gtemp1, 12);
  sensors.setResolution(gtemp2, 12);
  
//I2C portextender start
  PCF_01.begin(); // 8pcs output
  PCF_02.begin(); // 8pcs input

//Reset/clean up Cayenne dashboard after power failure or reset.
  Cayenne.loop();
       Cayenne.celsiusWrite(0, bme.readTemperature());
       Cayenne.virtualWrite(1, bme.readHumidity(), TYPE_RELATIVE_HUMIDITY, UNIT_PERCENT); //There is no predefined Write command.
       Cayenne.hectoPascalWrite(2, bme.readPressure()/100);
       sensors.requestTemperatures();
       Cayenne.celsiusWrite(3, sensors.getTempC(gtemp1));
       Cayenne.celsiusWrite(4, sensors.getTempC(gtemp2));
       Cayenne.digitalSensorWrite(9, PCF_02.readButton(0));
       Cayenne.digitalSensorWrite(10, PCF_02.readButton(1));
       Cayenne.digitalSensorWrite(11, PCF_02.readButton(2));
       Cayenne.digitalSensorWrite(12, PCF_02.readButton(3));
       Cayenne.digitalSensorWrite(13, PCF_02.readButton(4));
       Cayenne.digitalSensorWrite(14, PCF_02.readButton(5));
       Cayenne.digitalSensorWrite(15, PCF_02.readButton(6));
       Cayenne.digitalSensorWrite(16, PCF_02.readButton(7));
       Cayenne.virtualWrite(20,0);
       Cayenne.virtualWrite(21,0);
       Cayenne.virtualWrite(22,0);
       Cayenne.virtualWrite(23,0);
       Cayenne.virtualWrite(24,0);
       Cayenne.virtualWrite(25,0);
       Cayenne.virtualWrite(26,0);
       Cayenne.virtualWrite(27,0);
}

void loop() {
	Cayenne.loop();

// 8pcs input - PCF8574
// No status change, no message - try to avoid any unnecessary status update.

       S0 = PCF_02.readButton(0);
       if (S0 != S0e) {
       Cayenne.digitalSensorWrite(9, S0);
       S0e = S0;
       }

       S1 = PCF_02.readButton(1);
       if (S1 != S1e) {
       Cayenne.digitalSensorWrite(10, S1);
       S1e = S1;
       }

       S2 = PCF_02.readButton(2);
       if (S2 != S2e) {
       Cayenne.digitalSensorWrite(11, S2);
       S2e = S2;
       }

       S3 = PCF_02.readButton(3);
       if (S3 != S3e) {
       Cayenne.digitalSensorWrite(12, S3);
       S3e = S3;
       }

       S4 = PCF_02.readButton(4);
       if (S4 != S4e) {
       Cayenne.digitalSensorWrite(13, S4);
       S4e = S4;
       }

       S5 = PCF_02.readButton(5);
       if (S5 != S5e) {
       Cayenne.digitalSensorWrite(14, S5);
       S5e = S5;
       }

       S6 = PCF_02.readButton(6);
       if (S6 != S6e) {
       Cayenne.digitalSensorWrite(15, S6);
       S6e = S6;
       }

       S7 = PCF_02.readButton(7);
       if (S7 != S7e) {
       Cayenne.digitalSensorWrite(16, S7);
       S7e = S7;
       }

**//Reset the status of the three (3) "push buttons" on channel 22, 23 & 24.**
**//Unfortunately it should be updated frequently, since I cannot "reset" them from "CAYENNE_IN" directly**.
if(millis() - lastMillis3 > 3000) {
       lastMillis3 = millis();
       Cayenne.virtualWrite(22,0);
       Cayenne.virtualWrite(23,0);
       Cayenne.virtualWrite(24,0);
       }

//Data need just slow update.
   if(millis() - lastMillis2 > 120000) {
       lastMillis2 = millis();
     
       //BMP/BME280 szenzor
       Cayenne.celsiusWrite(0, bme.readTemperature());
       Cayenne.virtualWrite(1, bme.readHumidity(), TYPE_RELATIVE_HUMIDITY, UNIT_PERCENT); ////There is no predefined Write command.
       Cayenne.hectoPascalWrite(2, bme.readPressure()/100);
       
       //DS18B20 szenzorok
       sensors.requestTemperatures();  // Send the command to get temperatures.
       Cayenne.celsiusWrite(3, sensors.getTempC(gtemp1));
       Cayenne.celsiusWrite(4, sensors.getTempC(gtemp2));

       }
}


//Relay controls (8ch).

CAYENNE_IN(20) //GM
{
  PCF_01.write(0, !getValue.asInt());
}

CAYENNE_IN(21) //KM
{
  PCF_01.write(1, !getValue.asInt());
}

CAYENNE_IN(22) //GA - Should be a "push button", holding time 777ms, reset in the loop
{
  PCF_01.write(2, !getValue.asInt());
  delay(777);
  PCF_01.write(2, HIGH);
}

CAYENNE_IN(23) //GK - Should be a "push button", holding time 777ms, reset in the loop
{
  PCF_01.write(3, !getValue.asInt());
  delay(777);
  PCF_01.write(3, HIGH);
}

CAYENNE_IN(24) //BK - Should be a "push button", holding time 777ms, reset in the loop
{
  PCF_01.write(4, !getValue.asInt());
  delay(777);
  PCF_01.write(4, HIGH);
}

CAYENNE_IN(25) //Relé 6.
{
  PCF_01.write(5, !getValue.asInt());
}

CAYENNE_IN(26) //Relé 7.
{
  PCF_01.write(6, !getValue.asInt());
}

CAYENNE_IN(27) //Relé 8.
{
  PCF_01.write(7, !getValue.asInt());
}

//It might be useful for later.
/*
CAYENNE_IN(6)
{
  pinMode(2, OUTPUT);
  if (getValue.asInt() == 1)  //check the 0/1 value coming from the Cayenne widget
    {
    digitalWrite(2, HIGH);  
    }
  else
    {
    digitalWrite(2, LOW); 
    }
}
*/

//    tslfunc(VIRTUAL_PIN);
//    ds18b20func(VIRTUAL_PINT);
       //Some examples of other functions you can use to send data.
       //Cayenne.celsiusWrite(1, 22.0);
       //Cayenne.luxWrite(2, 700);
       //Cayenne.virtualWrite(3, 50, TYPE_PROXIMITY, UNIT_CENTIMETER);

#9

When you say push button are you talking about a button attached to a GPIO pin or a dashboard software button? Also you have an error in your comment here:

**//Reset the status of the three (3) "push buttons" on channel 22, 23 & 24.**
**//Unfortunately it should be updated frequently, since I cannot "reset" them from "CAYENNE_IN" directly**.

The // needs to come before the ** or just take the ** out as /* is a block comment.


#10

Thanks for all that Adam. Actually the project does highlight into a bold colour after a few seconds - possibly when the server “talks” to my board? So all good there and thanks for the explanation of online/offline triggers not working on MQTT Cayene. I assume the other triggers work OK?
Also any idea on why I cannot move the icons on my phone ap (to make a more sensible arrangement) and have them stay there - currently the next time I log in the icons are back where they started from.
Thanks again,
Craig


#11

Thank you for your fast reply!
Sorry, the stars **// are fault of formatting or fault of copy, there are no ** over there. (I have tried to format my code to make it more readable as I see in other’s nice reply, but I am too beginner yet :slight_smile: to do it on the right way)
The push button I have mentioned is a dashboard button/actuator. I have realized it by a relay, because I shall imitate a real momentary switch to interface my device to another one.
Unfortunately there is no momentary switch/push button actuator in Cayenne yet. This is why I created this not really elegant workaround.


#12

Pls check the following rows, starts with CAYENNE_IN!
These short delays realize the push button function toward to another hardware I shall interface to (my relays react to active “L”).

CAYENNE_IN(22) //GA - Should be a “push button”, holding time 777ms, reset in the loop
{
PCF_01.write(2, !getValue.asInt());
delay(777);
PCF_01.write(2, HIGH);
}

CAYENNE_IN(23) //GK - Should be a “push button”, holding time 777ms, reset in the loop
{
PCF_01.write(3, !getValue.asInt());
delay(777);
PCF_01.write(3, HIGH);
}

CAYENNE_IN(24) //BK - Should be a “push button”, holding time 777ms, reset in the loop
{
PCF_01.write(4, !getValue.asInt());
delay(777);
PCF_01.write(4, HIGH);
}

The following part do the button/actuator status reset on the Cayenne dashboard, because I did not find any, better solution yet to avoid clicking on the actuator button twice.

if(millis() - lastMillis3 > 3000) {
lastMillis3 = millis();
Cayenne.virtualWrite(22,0);
Cayenne.virtualWrite(23,0);
Cayenne.virtualWrite(24,0);
}


#13

can you give this a try : Switch button as pulse generator


#14

Thanks a lot, I will try it today evening!


#15

Dear shramiksalgaonkar,

I have tested your solution on last weekend and it works well, thanks a lot again!
But I have limited program memory in my device, therefore I have modified the code to make it shorter.
Since I am not a professional, it may not work in every cases, pls check it!
(I did not copied all the code here below, just the point to save space.)

//Home IoT solution with Wemos D1 Mini ver 2.2
#include <DallasTemperature.h>
#include <PCF8574.h>
// WiFi and MQTT credentials


int GD = 0; //Garage Door
int GG = 0; //Garage Gate
int PG = 0; //Parking place Gate


void setup() {
Serial.begin(9600);
Cayenne.begin(username, password, clientID, ssid, wifiPassword);


void loop() {
Cayenne.loop();


//Reset the status of the three (3) “push buttons” on channel 22, 23 & 24 after it was pressed.
if (GD == 1)
{
Cayenne.digitalSensorWrite(22, 0);
GD = 0;
}
if (GG == 1)
{
Cayenne.digitalSensorWrite(23, 0);
GG = 0;
}
if (PG == 1)
{
Cayenne.digitalSensorWrite(24, 0);
PG = 0;
}


}


//Relay controls (8ch).


//ACTIVE LOW relay module!
CAYENNE_IN(22) //GD - Pushbutton, it holds for 1 sec.
{
GD = getValue.asInt();
PCF_01.write(2, !GD);
delay(1000);
PCF_01.write(2, HIGH);
}
CAYENNE_IN(23) //GG - Pushbutton, it holds for 1 sec.
{
GG = getValue.asInt();
PCF_01.write(3, !GG);
delay(1000);
PCF_01.write(3, HIGH);
}
CAYENNE_IN(24) //PG - Pushbutton, it holds for 1 sec.
{
BK = getValue.asInt();
PCF_01.write(4, !PG);
delay(1000);
PCF_01.write(4, HIGH);
}