Publish to a Channel Using an Arduino Client | Arduino | Forum

Avatar

Please consider registering
Guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —






— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed sp_TopicIcon
Publish to a Channel Using an Arduino Client
No permission to create posts
June 28, 2019
2:17 am
Avatar
mac

Gold
Members
Forum Posts: 21
Member Since:
August 10, 2017
sp_UserOfflineSmall Offline

I have uploaded this Thingspeak code from your site to my Uno WiFi Rev2 ( replacing WiFi101 with WiFiNINA //Uno WiFi Rev 2)
https://au.mathworks.com/help/thingspeak/use-arduino-client-to-publish-to-a-channel.html

The Uno sucessfully connects to my wifi.
The uno successfully connects to MQTT (via port 1883)
No error messages received.

The Uno correctly writes temperature from the DHT22 to the Serial Monitor.

But there is no data being graphed on my Thingspeak channel!

Because the msgBuffer is EMPTY!!! see code below.
Code is deleting msgBuffer contents,why?

The channel ID is correct
The Write API is correct
A MQTT API has been created from my Profile and is in the code as char mqttPass[] = "W4...........";

void mqttpublish() {

float t = dht.readTemperature(); // Read temperature from DHT sensor.
Serial.print(F("T="));Serial.print(t);Serial.println(F("C"));
String data = String(t, DEC);
int length = data.length();
char msgBuffer[length];
data.toCharArray(msgBuffer,length+1);
Serial.println(msgBuffer); //correctly contains upload data

// Create a topic string and publish data to ThingSpeak channel feed.
String topicString ="channels/" + String( channelID ) + "/publish/"+String(writeAPIKey);
length=topicString.length();
char topicBuffer[length];
topicString.toCharArray(topicBuffer,length+1);

Serial.print(F("topicBuffer="));Serial.println(topicBuffer);
Serial.print(F("msgBuffer="));Serial.println(msgBuffer);//. msgBuffer is now EMPTY hence no thing to upload!!!

mqttClient.publish( topicBuffer, msgBuffer );

lastConnectionTime = millis();
}

I am currently uploading other data to another Channel from another device and have previously uploaded data to the channel that is not currently receiving the DHT22 data

June 28, 2019
10:24 am
Avatar
cstapels
Moderator
Members


Moderators
Forum Posts: 861
Member Since:
March 7, 2017
sp_UserOfflineSmall Offline

The UNO has a very small available memory. You might want to look at what libraries you are adding, for example to process your sensor data.
I would start by hard coding the msg buffer with a literal string ("channels/12345/publish/XXXXXXXXXXXX" and seeing if you can get that the write to ThingSpeak. You can disable the sensor library (if there is one) to see if it is a memory issue.
You also seem to have lost the text "field1" etc, which is required in the message buffer.
Last thing to look into is the library restriction on the size of the MQTT buffer. There is a related thread on the forum, but I cannot find it now. Basically you open the library and edit the line that says buffer size, but I don't think that is related to this problem.

June 28, 2019
10:41 am
Avatar
mac

Gold
Members
Forum Posts: 21
Member Since:
August 10, 2017
sp_UserOfflineSmall Offline

The code that i am using is as per the Thingspeak web site. Apart from my debug Serial.print lines.
I have tried both of the mqttpublish() functions.
Both have no msgBuffer content.

Here is the Serial Monitor display
field1=22.1000000000&field2=43.9000020000&field3=512
topicBuffer=channels/3*****3/publish/A***********9
msgBuffer=

Why is the msgBuffer empty just prior to the upload ?
mqttClient.publish( topicBuffer, msgBuffer );code

Here the ThingSpeak code for 3 fields

void mqttpublish() {

float t = dht.readTemperature(); // Read temperature from DHT sensor.
float h = dht.readHumidity(); // Read humidity from DHT sensor.
//int lightLevel = analogRead(LIGHTPIN); // Read voltage from light sensor.
int lightLevel=512;//temporary test data

Serial.print(F("T="));Serial.print(t);Serial.println(F("C"));

// Create data string to send to ThingSpeak.
String data = String("field1=" + String(t, DEC) + "&field2=" + String(h, DEC) + "&field3=" + String(lightLevel, DEC));
int length = data.length();
char msgBuffer[length];
data.toCharArray(msgBuffer,length+1);
Serial.println(msgBuffer);

// Create a topic string and publish data to ThingSpeak channel feed.
String topicString ="channels/" + String( channelID ) + "/publish/"+String(writeAPIKey);
length=topicString.length();
char topicBuffer[length];
topicString.toCharArray(topicBuffer,length+1);

Serial.print(F("topicBuffer="));Serial.println(topicBuffer);
Serial.print(F("msgBuffer="));Serial.println(msgBuffer);

mqttClient.publish( topicBuffer, msgBuffer );

lastConnectionTime = millis();
}

here is the IDE compile
Sketch uses 19136 bytes (38%) of program storage space. Maximum is 49152 bytes.
Global variables use 591 bytes (9%) of dynamic memory, leaving 5553 bytes for local variables. Maximum is 6144 bytes.

June 28, 2019
1:15 pm
Avatar
cstapels
Moderator
Members


Moderators
Forum Posts: 861
Member Since:
March 7, 2017
sp_UserOfflineSmall Offline

What does the F() do in this line?

Serial.print(F("msgBuffer="))
June 29, 2019
12:10 am
Avatar
mac

Gold
Members
Forum Posts: 21
Member Since:
August 10, 2017
sp_UserOfflineSmall Offline

from the Arduino site
https://www.arduino.cc/reference/en/language/variables/utilities/progmem/

The F() macro

When an instruction like :

Serial.print("Write something on the Serial Monitor");

is used, the string to be printed is normally saved in RAM. If your sketch prints a lot of stuff on the Serial Monitor, you can easily fill the RAM. If you have free FLASH memory space, you can easily indicate that the string must be saved in FLASH using the syntax:

Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));

June 29, 2019
12:27 am
Avatar
mac

Gold
Members
Forum Posts: 21
Member Since:
August 10, 2017
sp_UserOfflineSmall Offline

I have rewritten the ThingSpeak sample code using char arrays and not using any String constructs.
My code runs correctly.

Using String constructs is problematic on Arduinos and in my experience is not recommended
I refer you to an excellent article by Majenko
https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

Your earlier comment that the Arduino Uno has limited memory is true.
To quote from Majenko
Strings are a bit of a tricky area on the Arduino. The String object was created to make working with blocks of text easier for people that don’t really know what they are doing when it comes to low level C++ programming. However, if you don’t know what you’re doing when it comes to low level C++ programming then it is very easy to abuse the String object in such a way that it makes everything about your sketch fragile and unstable.

June 29, 2019
12:41 pm
Avatar
cstapels
Moderator
Members


Moderators
Forum Posts: 861
Member Since:
March 7, 2017
sp_UserOfflineSmall Offline

Glad you got it working. My working theory is that the specific problem was the flash write F() that you were using, but getting rid of the string implementation will be definitely helpful for you on the Uno. I think the code reads much nicer with the stings, but at the cost of tighter space for people using smaller memory sizes. Thanks for posting, this will be helpful for others who have this problem.

Forum Timezone: America/New_York

Most Users Ever Online: 166

Currently Online:
19 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

rw950431: 272

Vinod: 240

piajola: 95

turgo: 70

vespapierre: 63

Adarsh_Murthy: 62

Member Stats:

Guest Posters: 1

Members: 8665

Moderators: 1

Admins: 2

Forum Stats:

Groups: 3

Forums: 14

Topics: 1600

Posts: 5760

Newest Members:

briskpanda, Dejw0089, Yassine Ben Salah, anis, 43994554AKS, suda

Moderators: cstapels: 460

Administrators: Hans: 405, lee: 457