I am using Arduino UNO and a PN532 NFC module to receive P2P NDEF messages from an Android phone.
I am sending a plaintext string "Hello". When the transfer is successful, I get this on my Arduino:
image
How can I extract the string "Hello" (I think the pairs of numbers before it is the "Hello" in hexadecimal, same for the "text/plain" type indication, type length and payload length) from the NDEF message payload into a regular variable?
Here is my Arduino code:
// Receive a NDEF message from a Peer
// Requires SPI. Tested with Seeed Studio NFC Shield v2
#include "SPI.h"
#include "PN532_SPI.h"
#include "snep.h"
#include "NdefMessage.h"
PN532_SPI pn532spi(SPI, 10);
SNEP nfc(pn532spi);
uint8_t ndefBuf[128];
void setup() {
Serial.begin(9600);
Serial.println("NFC Peer to Peer Example - Receive Message");
}
void loop() {
Serial.println("Waiting for message from Peer");
//string payload = nfc.read();
int msgSize = nfc.read(ndefBuf, sizeof(ndefBuf));
NdefMessage msg = NdefMessage(ndefBuf, msgSize);
msg.print();
}
A NdefMessage is made up of multiple NdefRecord items and you msg has 1 record
so this should do it (not tested)
// Get the first record
NdefRecord record = msg.getRecord(0);
// Get the payload size
byte length = record.getPayloadLength();
// Create byte array big enough for payload
byte payload[length];
// Get payload to byte array
record.getPayload(payload);
// Convert byte Array to string
String string = String((char *)payload);
Related
I have a project in which I use an Arduino UNO and an esp8266-01.
The Arduino is used to gather water high and water low sensor information and then transmit that information over to turn on/off a latching relay for a water valve to fill my pool. It also turns off and on a solar panel to charge my batteries and also turns off and on the esp8266.
I want to be able to connect to the wifi every time the esp8266 comes on and then send water level sensor information and battery level sensor information up to thingSpeak.
In the following code I have made it so that the first time the esp8266 is powered up it tries to connect to the local wifi but since no ip and password is provided it go to access point mode and opens a sign in page. I also provide the user to input their thingSpeak write api. This data is saved to the esp8266's eeprom so that in the future it will auto connect and send information to thingSpeak. This works fine.
My problem is getting the information from the water level sensor and the battery level into the esp8266. I was first gathering the data on the Arduino and then having the esp8266 connect and upload the information using AT commands using SerialSoftware. However to get the AUTOCONNECT to work I had to reprogram the esp8266 and now it doesn't respond to AT commands. I have tried to reprogram the RX and TX pins on the ESP but it only has two reading when there is water present it reads 1024 and no water is 0. Nothing in between. The battery level doesn't register anything. Can I do this using the TX and RX pins somehow as an analog input or can I take the information (numbers) gathered on the Arduino and had them off to the ESP8266 using the TX (arduino) and RX (ESP)to send them to ThingSpeak. I am at a loss and need help.
Here is the code on the ESP8266
#include <FS.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <EEPROM.h>
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h>
//NEW STUFF START
char Password[36]="";
char apiKey[16]="";
WiFiClient client;
//eeprom new end
char defaultHost[100] = ""; //Thing Speak IP address (sometime the web address causes issues with ESP's :/
long itt = 500;
long itt2 = 500;
const byte wifiResetPin = 13;
int interruptPinDebounce = 0;
long debouncing_time = 1000;
volatile unsigned long wifiResetLastMillis = 0;
bool shouldSaveConfig = false;
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;}
void handleWifiReset(){
if(millis()<wifiResetLastMillis){
wifiResetLastMillis = millis();
}
if((millis() - wifiResetLastMillis)>= debouncing_time){
Serial.println("Clearing WiFi data resetting");
WiFiManager wifiManager;
wifiManager.resetSettings();
SPIFFS.format();
ESP.reset();
delay(1000);
}
wifiResetLastMillis = millis();
}
int addr = 0;
void setup() {
//EEPROM.begin(512); //Initialize EEPROM
WiFiManager wifiManager;
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(wifiResetPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(wifiResetPin), handleWifiReset,FALLING);
WiFiManagerParameter customAPIKey("apiKey", "ThingSpeakWriteAPI", apiKey, 16);
//END NEW STUFF
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
//WiFiManager wifiManager;
//NEW STUFF START
//wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&customAPIKey);
//END NEW STUFF
//reset saved settings
//wifiManager.resetSettings();
//set custom ip for portal
//wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
wifiManager.autoConnect("AutoConnectAP");
Serial.println("Connected");
//NEW STUFF START
strcpy(apiKey, customAPIKey.getValue());
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["defaultHost"] = defaultHost;
json["apiKey"] = apiKey;
Serial.println("API");
Serial.print(apiKey);
String apiKey2 = String(apiKey);
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(configFile);
json.printTo(Serial);
delay(1000);
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
//END NEW STUFF
//or use this for auto generated name ESP + ChipID
//wifiManager.autoConnect();
//Serial.println("WriteApi");
//Serial.println(apiKey);
//if you get here you have connected to the WiFi
//Serial.println("K)");
//save the custom parameters to FS
strcpy(apiKey,customAPIKey.getValue());
EEPROM.begin(512); //Initialize EEPROM
// write appropriate byte of the EEPROM.
// these values will remain there when the board is
// turned off.
EEPROM.write(addr, 'A'); //Write character A
addr++; //Increment address
EEPROM.write(addr, 'B'); //Write character A
addr++; //Increment address
EEPROM.write(addr, 'C'); //Write character A
//Write string to eeprom
String www = apiKey;
for(int i=0;i<www.length();i++) //loop upto string lenght www.length() returns length of string
{
EEPROM.write(0x0F+i,www[i]); //Write one by one with starting address of 0x0F
}
EEPROM.commit(); //Store data to EEPROM
//Read string from eeprom
}
//callback notifying us of the need to save config
void loop() {
Serial.begin(115200);
WiFiManager wifiManager;
if (WiFi.status() == WL_DISCONNECTED) {
wifiManager.autoConnect("AutoConnectAP");}
delay(5000);
if (WiFi.status() == WL_CONNECTED) { Serial.println("Connected");
WiFiClient client;
long itt = 500;
long itt2 = 500;
char defaultHost[100] = "api.thingspeak.com";
//HERE IS WHERE I CHANGE THE TX AND RX PIN FUNCTION
pinMode(1, FUNCTION_3);
pinMode(3, FUNCTION_3);
//THEN I ASSIGN THEM AS INPUT PINS
pinMode(1,INPUT);
pinMode(3,INPUT);
//ASSIGN EACH PIN TO AN INTERGER
const int waterInPin = 3; // Analog input pin that the potentiometer is attached to
const int BatteryInPin = 1; // Analog input pin that the battery is attached to
int waterSensorInValue;//reading our water lever sensor
int waterSensorOutValue;//conversion of water sensor value
int BatterySensorInValue;//reading our water lever sensor
int BatterySensorOutValue;//conversion of water sensor value
// put your main code here, to run repeatedly:
waterSensorInValue = analogRead(waterInPin);
BatterySensorInValue = analogRead(BatteryInPin);
waterSensorOutValue = map(waterSensorInValue,0,1024,0,225);
BatterySensorOutValue = map(BatterySensorInValue,0,1024,0,225);
Serial.println("WaterOutValue = ");
Serial.println(waterSensorOutValue );
Serial.println("WaterInValue = ");
Serial.println(waterSensorInValue );
Serial.println("BatteryOutValue = ");
Serial.println(BatterySensorOutValue );
Serial.println("BatteryInValue = ");
Serial.println(BatterySensorInValue);
//ASSIGN THE INPUT VALUES TO UPLOAD LONGS
itt = waterSensorInValue;
itt2 = BatterySensorInValue;
EEPROM.begin(512);
Serial.println(""); //Goto next line, as ESP sends some garbage when you reset it
Serial.print(char(EEPROM.read(addr))); //Read from address 0x00
addr++; //Increment address
Serial.print(char(EEPROM.read(addr))); //Read from address 0x01
addr++; //Increment address
Serial.println(char(EEPROM.read(addr))); //Read from address 0x02
//Read string from eeprom
String www;
//Here we dont know how many bytes to read it is better practice to use some terminating character
//Lets do it manually www.circuits4you.com total length is 20 characters
for(int i=0;i<16;i++)
{
www = www + char(EEPROM.read(0x0F+i)); //Read one by one with starting address of 0x0F
}
Serial.print(www); //Print the text on serial monitor
if (client.connect(defaultHost,80))
{ // "184.106.153.149" or api.thingspeak.com
itt++; //Replace with a sensor reading or something useful
//UPLOAD TO THINGSPEAK
String postStr = www;
postStr +="&field1=";
postStr += String(itt);
postStr +="&field2=";
postStr += String(itt2);
postStr += "\r\n\r\n\r\n";
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: "+String (www)+"\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(postStr.length());
client.print("\n\n\n");
client.print(postStr);
Serial.println("% send to Thingspeak");
}
client.stop();
Serial.println("Waiting…");
}
delay(55000);
}
As I said almost everything works ok. The ESP8266 comes on when the Arduino turns it on. The sensor comes on and gets the value. A value is uploaded to ThingSpeak (just not a useful one.
Any Ideas, suggestions, examples, tutorials will be greatly appreciated. Thanks.
My suggestion is use only one ESP32 to do all this work.
It´s much simpler and easier than using two micro-controllers.
You can use the ESP32 to read and send the sensor data and save the trouble of communicating two different micros.
I am trying to publish sensor data using esp_mqtt library to thingsboard.io dashboard. But the connection between the library and thingsboard is not getting established. I am using esp8266 nodeMCU v2 and platformIO
Here is the link to the esp_mqtt library documentation.
https://github.com/tuanpmt/esp_mqtt/blob/master/README.md
Here is the code snippet :
#include <ESP8266WiFi.h>
#include <MQTT.h>
#define CLIENT_ID "client1"
#define TOPIC "v1/devices/me/telemetry"
#define TOKEN "access token"
MQTT myMqtt(CLIENT_ID,"localhost",1883);
const char* ssid = "ssid";
const char* password = "password";
void setup() {
Serial.begin(115200);
delay(1000);
setup_wifi();
Serial.println("Connecting to MQTT server");
// setup callbacks
myMqtt.onConnected(myConnectedCb);
myMqtt.onDisconnected(myDisconnectedCb);
myMqtt.onPublished(myPublishedCb);
myMqtt.onData(myDataCb);
Serial.println("connect mqtt...");
myMqtt.setClientId(CLIENT_ID);
myMqtt.setUserPwd(TOKEN,"");
myMqtt.connect();
Serial.println("subscribe to topic...");
myMqtt.subscribe(TOPIC);
delay(10);
}
void loop() {
float value = analogRead(A0);
String temp=String(value);
// publish value to topic
String payload = "{";
//payload += "\"temperature\":"; payload += temperature; payload += ",";
payload += "\"temperature\":"; payload += temp;
payload += "}";
// Send payload
char attributes[100];
payload.toCharArray( attributes, 100 );
//String(attributes);
boolean result = myMqtt.publish("v1/devices
/me/telemetry",attributes,100,1,0);
delay(1000);
}
You are trying to connect to localhost unless you are running a broker on the ESP8266 this is never going to work.
You need to know what the host name of thingsboard.io's broker is and replace localhost with that value. The port number may also need changing.
I'm also guessing the clientid may need to be something a little more unique than client1
Sorry if my post is not well formatted'm new in here.
/*
SimpleSend
This sketch transmits a short text message using the VirtualWire library
connect the Transmitter data pin to Arduino pin 12
*/
#include <VirtualWire.h>
String Mensagem = "eureca"; //I want to send this string
void setup(){
// Initialize the IO and ISR
vw_setup(2000); // Bits per sec
}
void loop(){
send(Mensagem); //Putting a string inside the function does not work,
//I want to send a String message inside that function like a parameter
delay(1000);
}
void send (char *message){
vw_send((uint8_t *)message, strlen(message));
vw_wait_tx(); // Wait until the whole message is gone
}
char *message means a string literal or a character pointer, but what you're passing into the function is a String.
You can fix it by using:
char Mensagem[]= "eureca";
in order to match the type. It's because Mensagem now is a static pointer of that character array.
I have an arduino sketch, that listens for RFID tags, and gets their uid's and stores them in an array of uint32_t
This is an arduino_uno project with an adaFruit BTLE and as adafruit NFC/RFID Shield
The array is initiated like so:
uint32_t items[]= { 0,0,0,0,0,0};
Then in my loop();
I find an id like so:
success = nfc1.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
//
Serial.println(success,DEC);
if (success) {
// Display some basic information about the card
//Serial.println("Found an ISO14443A card");
//Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
//Serial.print(" UID Value: ");
nfc1.PrintHex(uid, uidLength);
if (uidLength == 4)
{
// We probably have a Mifare Classic card ...
cardid = uid[0];
cardid <<= 8;
cardid |= uid[1];
cardid <<= 8;
cardid |= uid[2];
cardid <<= 8;
cardid |= uid[3];
Serial.print("Seems to be a Mifare Classic card #");
Serial.println(cardid);
BTLEserial.print(cardid);
}
Serial.println("");
}
Not that that block of code prints out to the Serial Monitor this:
Seems to be a Mifare Classic card #347161076
Writing out
to BTLE: 0x31 0x36 0x38 0x38 0x34
But the BTLE app is seeing
16884
" as the cardid?
It seems obvious that this is do to some weird byte conversion on the uint32_tbeing handled by the BTLEserial.print() method.
As i find id's I am storeing up to six of them in the items array above. I would like to send that entire array via blue tooth to my device, as a comma separated string.
Please help convert this uint32_t to either a string or other object that can be handled by the BTLE
I figured it out by using this method:
int radix =10;
char buffer[33];
char* getStringForUI32_T(uint32_t value){
return ultoa(value,buffer,radix);
}
I was trying to upload a Xively feed with an Arduino connected via an Arduino GSM shield.
Xively does not publish any specific example for an Arduino GSM shield. I tried to use the Arduino GSM Pachube Client library changing "pachube.com" in "xively.com", but it did not work. It seems that my GSM shield is able to connect but cannot put the data to the server.
In my example I created a device called "Arduino GSM" with just one channel called "sensor1". In the request log I cannot read any request incoming, although the serial monitor shows that a connection with the server occurs.
This is the code I tried:
// Original GSM Pachube client modified for Xively
// Changes: pachube.com -> xively.com
// inserted APIKEY, FEEDID, USERAGENT
// inserted GPRS_APN, login, password
/*GSM Pachube client
This sketch connects an analog sensor to Pachube (http://www.pachube.com)
using a Telefonica GSM/GPRS shield.
This example has been updated to use version 2.0 of the Pachube.com API.
To make it work, create a feed with a datastream, and give it the ID
sensor1. Or change the code below to match your feed.
Circuit:
* Analog sensor attached to analog in 0
* GSM shield attached to an Arduino
* SIM card with a data plan
created 4 March 2012
by Tom Igoe
and adapted for GSM shield by David Del Peral
This code is in the public domain.
http://arduino.cc/en/Tutorial/GSMExamplesPachubeClient
*/
// libraries
#include <GSM.h>
// Pachube Client data -> changed in Xively Data
#define APIKEY "myapikey" // replace your pachube api key here
#define FEEDID 111111111 // replace your feed ID
#define USERAGENT "Arduino GSM" // user agent is the project name
// PIN Number
#define PINNUMBER ""
// APN data
#define GPRS_APN "WINDBIZ WEB" // replace your GPRS APN
#define GPRS_LOGIN "" // replace with your GPRS login
#define GPRS_PASSWORD "" // replace with your GPRS password
// initialize the library instance:
GSMClient client;
GPRS gprs;
GSM gsmAccess;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
// IPAddress server(216,52,233,121); // numeric IP for api.pachube.com
char server[] = "api.xively.com"; // name address for pachube API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to Pachube.com
void setup()
{
// initialize serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// connection state
boolean notConnected = true;
// After starting the modem with GSM.begin()
// attach the shield to the GPRS network with the APN, login and password
while(notConnected)
{
if((gsmAccess.begin(PINNUMBER)==GSM_READY) &
(gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD)==GPRS_READY))
notConnected = false;
else
{
Serial.println("Not connected");
delay(1000);
}
}
}
void loop()
{
// read the analog sensor:
int sensorReading = analogRead(A0);
// 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)
{
client.stop();
}
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && ((millis() - lastConnectionTime) > postingInterval))
{
sendData(sensorReading);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}
/*
This method makes a HTTP connection to the server.
*/
void sendData(int thisData)
{
// if there's a successful connection:
if (client.connect(server, 80))
{
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.print("Host: api.xively.com\n");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");
// calculate the length of the sensor reading in bytes:
// 8 bytes for "sensor1," + number of digits of the data:
int thisLength = 8 + getLength(thisData);
client.println(thisLength);
// last pieces of the HTTP PUT request:
client.print("Content-Type: text/csv\n");
client.println("Connection: close");
client.println();
// here's the actual content of the PUT request:
client.print("sensor1,");
client.println(thisData);
}
else
{
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted
lastConnectionTime = millis();
}
/*
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;
}