The problem is the value of +IPD response isn't show up at the ReadLastEntryThingSpeak(), so my code isn't correct or I must add something? I have searched for many websites Arduino forum, Thingspeak forum, and others. But I didn't see any solution. :(
I have tried to do this system for 5 days and it doesn't work, why?
#include <SoftwareSerial.h>
#include <string.h>
#define esp8266 Serial1
#define SSID "test" // put here the name of your wifi network
#define PASS "lolman123"
#define IP "184.106.153.149"
int counter = 120;
String keep;
String valuetosend;
const byte maxDataLength = 30; // maxDataLength is the maximum length
allowed for received data.
char receivedChars[31] ;
boolean newData = false;
String GET = "GET /update?key=FYPW04TOYR3FX2QH&"; // put here your
thingspeak key
String GET1 = "field1=";
String readGET1 = "GET
https://api.thingspeak.com/channels/864152/fields/1/last";
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
esp8266.begin(115200);
esp8266.println("AT");
delay(5000);
if(esp8266.find("OK")){
connectWiFi();
Serial.println("WIFI CONNECTED");
}
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
newData = false;
}
void loop() {
// put your main code here, to run repeatedly:
int readBtn = digitalRead(7);
int readSend = digitalRead(8);
if (readBtn == 0)
{
ReadLastEntryThingSpeak();
}
if (readSend == 0)
{
WriteThingSpeak();
}
}
boolean connectWiFi(){
esp8266.println("AT+CWMODE=1");
delay(2000);
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
esp8266.println(cmd);
delay(5000);
if(esp8266.find("OK")){
Serial.println("OK");
return true;
}else{
Serial.println("KO");
return false;
}
}
void updateFunction(String valuetosend){
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
esp8266.println(cmd);
delay(2000);
if(esp8266.find("Error")){
Serial.print("Error1");
return;
}
cmd = GET + GET1;
cmd += valuetosend;
cmd += "\r\n";
Serial.print(cmd);
esp8266.print("AT+CIPSEND=");
esp8266.println(cmd.length());
if(esp8266.find(">")){
esp8266.print(cmd);
}else{
esp8266.println("AT+CIPCLOSE");
}
}
void ReadLastEntryThingSpeak()
{
String cmd = "AT+CIPSTART=\"TCP\",\""; //connect to thingspeak
cmd += IP;
cmd += "\",80";
esp8266.println(cmd);
delay(2000);
if(esp8266.find("Error")){
Serial.print("Error1");
return;
}
cmd = readGET1;
cmd += "\r\n";
Serial.print(cmd);
esp8266.print("AT+CIPSEND=");
esp8266.println(cmd.length());
if(esp8266.find(">")){
esp8266.print(cmd);
}else{
esp8266.println("AT+CIPCLOSE");
}
delay(2000);
recvWithStartEndMarkers(); // check to see if we have
received any new commands
if (newData) { processCommand(); }
}
void WriteThingSpeak ()
{
String valuetosend = String(counter);
updateFunction(valuetosend);
}
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = ':';
char endMarker = 'C';
if (esp8266.available() > 0)
{
char rc = esp8266.read();
if (recvInProgress == true)
{
if (rc != endMarker)
{
if (ndx < maxDataLength) { receivedChars[ndx] = rc;
ndx++; }
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) { recvInProgress = true; }
}
}
void processCommand()
{
Serial.print("Recieved data = "); Serial.println(receivedChars);
newData = false;
}
I have the result of Received data = , but the actual output is Received data = 120.
Related
I am trying to create a music box for my son, but i am having some trouble getting the SD card to work.
The idea is that when we scan a RFID tag we should get the corresponding mp3 file from the SD card.
I am using:
a ESP32 DOIT DEVKIT V1
RFID reader is a RFID-RC522
Micro SD card reader has no brand or model number on it. It just says "Micro sd card adapter" on the back and has 6 pins: cs, sck, mosi, miso, vcc, gnd
My problem is that both the RFID reader and the Micro SD Card reader should use SPI.
With the following code the RFID Card is working well. I just have no idea on how to add the SD Card reader (i have tried using the same pins as the rfid reader and also the HSPI pins, but without success!)
Any help is much appreciated!
#include <SPI.h>
#include <MFRC522.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <WebSocketsServer.h>
#include <ArduinoJson.h>
#include "web_index.h"
// Constants
const char *ssid = "****";
const char *password = "****";
const int dns_port = 53;
const int http_port = 80;
const int ws_port = 1337;
// Globals
AsyncWebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(1337);
char msg_buf[10];
// Tag reader variables
#define RFID_RC522_RST_PIN 27
#define RFID_RC522_SDA_PIN 5
MFRC522 mfrc522(RFID_RC522_SDA_PIN, RFID_RC522_RST_PIN);
bool rfid_tag_present_prev = false;
bool rfid_tag_present = false;
int _rfid_error_counter = 0;
bool _tag_found = false;
// Volume Variables
int VOLUME = 15;
int VOLUME_NORMAL_MAX = 30;
int VOLUME_LIMIT_MAX = 15;
int VOLUME_MAX = VOLUME_NORMAL_MAX;
int VOLUME_MIN = 0;
int VOLUME_CHANGE_AMOUNT = 1;
bool VOLUME_IS_LIMITED = false;
// Player variables
bool IS_PLAYING = false;
String TRACK_NAME = "-";
String ARTIST_NAME = "-";
// Button variables
const int BUTTON_VOL_DOWN_PIN = 34;
bool BUTTON_VOL_DOWN_STATE = HIGH;
bool BUTTON_VOL_DOWN_PREV_STATE = HIGH;
const int BUTTON_VOL_UP_PIN = 35;
bool BUTTON_VOL_UP_STATE = HIGH;
bool BUTTON_VOL_UP_PREV_STATE = HIGH;
const int BUTTON_STOP_PIN = 32;
bool BUTTON_STOP_STATE = HIGH;
bool BUTTON_STOP_PREV_STATE = HIGH;
const int BUTTON_NEXT_PIN = 33;
bool BUTTON_NEXT_STATE = HIGH;
bool BUTTON_NEXT_PREV_STATE = HIGH;
// Tag IDs
String TAG_TEST = "93 44 5C 92";
String TAG_BACH = "9C CD 69 0F";
/***********************************************************
Functions
*/
void volumeDecrease() {
if (VOLUME > VOLUME_MIN) {
VOLUME = VOLUME - VOLUME_CHANGE_AMOUNT;
broadcastUpdate();
}
}
void volumeIncrease() {
if (VOLUME < VOLUME_MAX) {
VOLUME = VOLUME + VOLUME_CHANGE_AMOUNT;
broadcastUpdate();
} else {
VOLUME = VOLUME_MAX;
broadcastUpdate();
}
}
void updateVolumeLimitState(bool state) {
VOLUME_IS_LIMITED = state;
broadcastUpdate();
}
void broadcastUpdate() {
DynamicJsonDocument doc(1024);
doc["volume"] = VOLUME;
doc["volume_min"] = VOLUME_MIN;
doc["volume_max"] = VOLUME_MAX;
doc["volume_is_limited"] = VOLUME_IS_LIMITED;
doc["is_playing"] = IS_PLAYING;
doc["track_name"] = TRACK_NAME;
doc["artist_name"] = ARTIST_NAME;
char json_string[1024];
serializeJson(doc, json_string);
webSocket.broadcastTXT(json_string);
}
void handleWsTextMessage(uint8_t client_num, uint8_t * payload) {
if ( strcmp((char *)payload, "getValues") == 0 ) {
broadcastUpdate();
} else if ( strcmp((char *)payload, "volume_down_button_click") == 0 ) {
volumeDecrease();
} else if ( strcmp((char *)payload, "volume_up_button_click") == 0 ) {
volumeIncrease();
} else if ( strcmp((char *)payload, "volume_limit_checkbox_on") == 0 ) {
updateVolumeLimitState(true);
} else if ( strcmp((char *)payload, "volume_limit_checkbox_off") == 0 ) {
updateVolumeLimitState(false);
} else { // Message not recognized
Serial.println("[%u] Message not recognized");
}
}
// Callback: receiving any WebSocket message
void onWebSocketEvent(uint8_t client_num, WStype_t type, uint8_t * payload, size_t length) {
// Figure out the type of WebSocket event
switch (type) {
// Client has disconnected
case WStype_DISCONNECTED:
Serial.printf("[%u] Disconnected!\n", client_num);
break;
// New client has connected
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(client_num);
Serial.printf("[%u] Connection from ", client_num);
Serial.println(ip.toString());
}
break;
// Handle text messages from client
case WStype_TEXT:
// Print out raw message
Serial.printf("[%u] Received text: %s\n", client_num, payload);
handleWsTextMessage(client_num, payload);
break;
// For everything else: do nothing
case WStype_BIN:
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
default:
break;
}
}
// Callback: send homepage
void onIndexRequest(AsyncWebServerRequest *request) {
const char* dataType = "text/html";
IPAddress remote_ip = request->client()->remoteIP();
Serial.println("[" + remote_ip.toString() +
"] HTTP GET request of " + request->url());
// request->send(SPIFFS, "/index.html", "text/html");
AsyncWebServerResponse *response = request->beginResponse_P(200, dataType, index_html_gz, index_html_gz_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
// Callback: send 404 if requested file does not exist
void onPageNotFound(AsyncWebServerRequest *request) {
IPAddress remote_ip = request->client()->remoteIP();
Serial.println("[" + remote_ip.toString() +
"] HTTP GET request of " + request->url());
request->send(404, "text/plain", "Not found");
}
/***********************************************************
Main
*/
void handleButtons() {
// VOLUME DOWN BUTTON
bool buttonVolDownState = digitalRead(BUTTON_VOL_DOWN_PIN);
if (buttonVolDownState == LOW && BUTTON_VOL_DOWN_PREV_STATE == HIGH) {
Serial.println("button down pressed");
volumeDecrease();
BUTTON_VOL_DOWN_PREV_STATE = LOW;
} else if (buttonVolDownState == HIGH && BUTTON_VOL_DOWN_PREV_STATE == LOW) {
BUTTON_VOL_DOWN_PREV_STATE = HIGH;
}
// VOLUME UP BUTTON
bool buttonVolUpState = digitalRead(BUTTON_VOL_UP_PIN);
if (buttonVolUpState == LOW && BUTTON_VOL_UP_PREV_STATE == HIGH) {
Serial.println("button up pressed");
volumeIncrease();
BUTTON_VOL_UP_PREV_STATE = LOW;
} else if (buttonVolUpState == HIGH && BUTTON_VOL_UP_PREV_STATE == LOW) {
BUTTON_VOL_UP_PREV_STATE = HIGH;
}
// STOP BUTTON
bool buttonStopState = digitalRead(BUTTON_STOP_PIN);
if (buttonStopState == LOW && BUTTON_STOP_PREV_STATE == HIGH) {
Serial.println("button stop pressed");
volumeIncrease();
BUTTON_STOP_PREV_STATE = LOW;
} else if (buttonStopState == HIGH && BUTTON_STOP_PREV_STATE == LOW) {
BUTTON_STOP_PREV_STATE = HIGH;
}
// NEXT BUTTON
bool buttonNextState = digitalRead(BUTTON_NEXT_PIN);
if (buttonNextState == LOW && BUTTON_NEXT_PREV_STATE == HIGH) {
Serial.println("button next pressed");
volumeIncrease();
BUTTON_NEXT_PREV_STATE = LOW;
} else if (buttonNextState == HIGH && BUTTON_NEXT_PREV_STATE == LOW) {
BUTTON_NEXT_PREV_STATE = HIGH;
}
}
String getTagUid() {
String content = "";
byte letter;
for (byte i = 0; i < mfrc522.uid.size; i++) {
content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
content.concat(String(mfrc522.uid.uidByte[i], HEX));
}
content.toUpperCase();
String tag_uid = content.substring(1);
Serial.println("Getting tag uid");
Serial.println(content.substring(1));
return content.substring(1);
}
void checkTagValidity(String tag_uid) {
if (tag_uid == TAG_TEST) {
Serial.println("BLUE TAG");
ARTIST_NAME = "Blue Tag";
TRACK_NAME = "Super Track name";
IS_PLAYING = true;
broadcastUpdate();
} else if (tag_uid == TAG_BACH) {
Serial.println("BACH");
} else {
Serial.println("UNKNOWN CARD: ");
Serial.print(tag_uid);
}
}
void setup() {
// Init buttons
pinMode(BUTTON_VOL_DOWN_PIN, INPUT_PULLUP);
pinMode(BUTTON_VOL_UP_PIN, INPUT_PULLUP);
pinMode(BUTTON_STOP_PIN, INPUT_PULLUP);
pinMode(BUTTON_NEXT_PIN, INPUT_PULLUP);
// Start Serial port
Serial.begin(115200);
// Init SPI bus (for the tag reader)
SPI.begin();
// Init the tag reader
mfrc522.PCD_Init();
// Start access point
WiFi.softAP(ssid, password);
// Print our IP address
Serial.println();
Serial.println("AP running");
Serial.print("My IP address: ");
Serial.println(WiFi.softAPIP());
// On HTTP request for root, provide index.html file
server.on("/", HTTP_GET, onIndexRequest);
// 404 page
server.onNotFound(onPageNotFound);
// Start web server
server.begin();
// Start WebSocket server and assign callback
webSocket.begin();
webSocket.onEvent(onWebSocketEvent);
}
void loop() {
// Check for button clicks
handleButtons();
// Look for and handle WebSocket data
webSocket.loop();
rfid_tag_present_prev = rfid_tag_present;
_rfid_error_counter += 1;
if (_rfid_error_counter > 2) {
_tag_found = false;
}
// Detect Tag without looking for collisions
byte bufferATQA[2];
byte bufferSize = sizeof(bufferATQA);
// Reset baud rates
mfrc522.PCD_WriteRegister(mfrc522.TxModeReg, 0x00);
mfrc522.PCD_WriteRegister(mfrc522.RxModeReg, 0x00);
// Reset ModWidthReg
mfrc522.PCD_WriteRegister(mfrc522.ModWidthReg, 0x26);
MFRC522::StatusCode result = mfrc522.PICC_RequestA(bufferATQA, &bufferSize);
if (result == mfrc522.STATUS_OK) {
if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
return;
}
_rfid_error_counter = 0;
_tag_found = true;
}
rfid_tag_present = _tag_found;
// rising edge
if (rfid_tag_present && !rfid_tag_present_prev) {
Serial.println("Tag found");
// Get tag uid
String tag_uid = getTagUid();
// Check if valid tag
checkTagValidity(tag_uid);
}
// falling edge
if (!rfid_tag_present && rfid_tag_present_prev) {
Serial.println("Tag gone");
ARTIST_NAME = "-";
TRACK_NAME = "-";
IS_PLAYING = false;
broadcastUpdate();
}
}
Thanks to the comments from #romkey and #RamyHx i got it to work using the same SPI pins.
My problem was that i was using the same pin for the CS of both devices. Once i change it to different CS pins for the rfid and sd card reader it started working.
For the RFID i have used the pin D2, and for the sd card reader i have used the pin D5.
For the rfid i have change #define RFID_RC522_SDA_PIN 5 into #define RFID_RC522_SDA_PIN 2.
For the sd card i have used the code here, which assumes we are using the default pins (with CS connected to pin D5).
I'm writing a code to take pictures if the distance is more than a certain distance after measuring the distance.
And send the distance data to Thingspeak, Store the photos on the SD card.
However, the program keeps stopping in the middle.
Serial moniter capture
Distance measurement and Thingspeak server data transfer / camera shooting were developed separately.
The two source codes worked normally independently.
But when the two codes are combined, there is an error.
Parts for Use : Arduino Uno, esp8266 wifi module, TTL Serial JPEG Camera with NTSC Video, 2Y0A21 Infrared Distance Sensor, Micro SD card adapter
#include <SoftwareSerial.h>
#include <stdlib.h>
#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SD.h>
#define DEBUG true
#define chipSelect 10
const int distancePin = 0;
String apiKey = "39R00EYW0BTKK5JJ";
SoftwareSerial esp8266(2, 3); //TX/RX
#if ARDUINO >= 100
SoftwareSerial cameraconnection = SoftwareSerial(4, 5); //TX/RX
#else
NewSoftSerial cameraconnection = NewSoftSerial(4, 5);
#endif
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);
int defaultDistance = 0;
int temp = 0;
void ThingspeakSendData(String alarmData);
void Snapshots();
void setup() {
#if !defined(SOFTWARE_SPI)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega
#else
if (chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc.
#endif
#endif
Serial.begin(9600);
Serial.println("VC0706 Camera snapshot test");//the program keeps stopping in the middle.
if (cam.begin()) {
Serial.println("Camera Found:");
}
else {
Serial.println("No camera found?");
return;
}
char *reply = cam.getVersion();
if (reply == 0) {
Serial.print("Failed to get version");
}
else {
Serial.println("-----------------");
Serial.print(reply);
Serial.println("-----------------");
}
cam.setImageSize(VC0706_640x480);
uint8_t imgsize = cam.getImageSize();
Serial.print("Image size: ");
if (imgsize == VC0706_640x480) Serial.println("640x480");
if (imgsize == VC0706_320x240) Serial.println("320x240");
if (imgsize == VC0706_160x120) Serial.println("160x120");
esp8266.begin(9600);
sendData("AT+RST\r\n", 2000, DEBUG); //reset module
sendData("AT+CWMODE=1\r\n", 1000, DEBUG); //dual mode로 설정
sendData("AT+CWJAP=\"0sangsiljangnim\",\"123456788\"\r\n", 5000, DEBUG);
// 2Y0A21
analogReference(DEFAULT);
pinMode(distancePin, INPUT);
// distancePin 2Y0A21
int raw = analogRead(distancePin);
int volt = map(raw, 0, 1023, 0, 5000);
int distance = (21.61 / (volt - 0.1696)) * 1000;
defaultDistance = distance;
Serial.println("Default : " + defaultDistance);
}
void loop() {
// distancePin 2Y0A21
int raw = analogRead(distancePin);
int volt = map(raw, 0, 1023, 0, 5000);
int distance = (21.61 / (volt - 0.1696)) * 1000;
Serial.println(distance);
if (distance < defaultDistance)
{
String alarmData = "1";
esp8266.listen();
ThingspeakSendData(alarmData);
cameraconnection.listen();
Snapshots();
}
else if (distance == defaultDistance)
{
String alarmData = "0";
esp8266.listen();
ThingspeakSendData(alarmData);
}
delay(3000);
}
void ThingspeakSendData(String alarmData) {
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += "184.106.153.149";
cmd += "\",80";
esp8266.println(cmd);
if (esp8266.find("Error")) {
Serial.println("AT+CIPSTART error");
return;
}
String getStr = "GET /update?api_key=";
getStr += apiKey;
getStr += "&field1=";
getStr += String(alarmData);
getStr += "\r\n\r\n";
// Send Data
cmd = "AT+CIPSEND=";
cmd += String(getStr.length());
esp8266.println(cmd);
if (esp8266.find(">")) {
esp8266.print(getStr);
}
else {
esp8266.println("AT+CIPCLOSE");
// alert uesp8266
Serial.println("AT+CIPCLOSE");
}
}
String sendData(String command, const int timeout, boolean debug) {
String response = "";
esp8266.print(command);
long int time = millis();
while ((time + timeout) > millis()) {
while (esp8266.available()) {
char c = esp8266.read();
response += c;
}
}
if (debug) {
Serial.print(response);
}
return response;
}
void Snapshots() {
Serial.println("Snap in 3 secs...");
delay(3000);
if (!cam.takePicture())
Serial.println("Failed to snap!");
else
Serial.println("Picture taken!");
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
return;
}
char filename[13];
strcpy(filename, "IMAGE00.JPG");
for (int i = 0; i < 100; i++) {
filename[5] = '0' + i / 10;
filename[6] = '0' + i % 10;
if (!SD.exists(filename)) {
break;
}
}
File imgFile = SD.open(filename, FILE_WRITE);
uint16_t jpglen = cam.frameLength();
Serial.print("Storing ");
Serial.print(jpglen, DEC);
Serial.print(" byte image.");
int32_t time = millis();
pinMode(8, OUTPUT);
byte wCount = 0;
while (jpglen > 0) {
uint8_t *buffer;
uint8_t bytesToRead = min(32, jpglen);
buffer = cam.readPicture(bytesToRead);
imgFile.write(buffer, bytesToRead);
if (++wCount >= 64) {
Serial.print('.');
wCount = 0;
}
jpglen -= bytesToRead;
}
imgFile.close();
time = millis() - time;
Serial.println("done!");
Serial.print(time); Serial.println(" ms elapsed");
}
Situation: I have a webpage that has two buttons on it. One sends to the PubNub channel a JSON string of {"lightRight":"1"} and one sends {"lightRight":"0"}, regardless of what I do in the Arduino Sketch I cannot make it into the "on" portion of the void light function.
I know from the serial output of the arduino that I am receiving communication from the web page. If I flip my boolean values to off then I am able to get the "LED HIGH" output but then no longer can I get the "led low".
The code I am trying to adapt can be found here.
https://gist.github.com/ianjennings/ada8fb1a91a486a0c73e
It is very possible I have hacked out to much code from the examples that is why I am including it, but running the stock code I cannot seem to get this to work.
I am not a developer, so I am very sorry if I do not call things as their proper terms. I will learn from correction.
#include <PubNub.h>
#include <SPI.h>
#include <EthernetV2_0.h>
#include <string.h>
#include <Servo.h>
byte mac[] = { MAC was here };
byte gateway[] = { Gate was here };
byte subnet[] = { Sub was here };
IPAddress ip(IP was here);
char pubkey[] = "Key was here";
char subkey[] = "Key was here";
char channel[] = "Channel was here";
int lightRight = 5;
int lightRoom = 6;
int lightGarage = 7;
int i;
EthernetClient *client;
#define W5200_CS 3
#define SDCARD_CS 4
void setup()
{
pinMode(SDCARD_CS,OUTPUT);
digitalWrite(SDCARD_CS,HIGH);
Serial.begin(9600);
Serial.println("Serial set up");
while (!Ethernet.begin(mac)) {
Serial.println("Ethernet setup error");
blink(1000, 999999);
delay(1000);
}
Serial.println("Ethernet set up");
PubNub.begin(pubkey, subkey);
Serial.println("PubNub set up");
pinMode(lightRight, OUTPUT);
pinMode(lightRoom, OUTPUT);
pinMode(lightGarage, OUTPUT);
// blink(100, 5);
reset();
}
//void flash(int ledPin)
//{
// for (int i = 0; i < 3; i++) {
// Serial.println("flash");
// digitalWrite(ledPin, HIGH);
// delay(100);
// digitalWrite(ledPin, LOW);
// delay(100);
// }
//}
void loop()
{
Ethernet.maintain();
PubSubClient *client;
Serial.println("waiting for a message (subscribe)");
client = PubNub.subscribe(channel);
if (!client) {
Serial.println("subscription error");
return;
}
String messages[10];
boolean inside_command = false;
int num_commands = 0;
String message = "";
char c;
while (client->wait_for_data()) {
c = client->read();
if(inside_command && c != '"') {
messages[num_commands] += c;
}
if(c == '"') {
if(inside_command) {
num_commands = num_commands + 1;
inside_command = false;
} else {
inside_command = true;
}
}
message += c;
}
client->stop();
for (i = 0; i < num_commands; i++){
int colonIndex = messages[i].indexOf(':');
String subject = messages[i].substring(0, colonIndex);
String valueString = messages[i].substring(colonIndex + 1, messages[i].length());
boolean value = false;
if(valueString == "1") {
value = true;
}
if(subject == "lightRight") {
light(lightRight, value);
}
if(subject == "lightRoom") {
light(lightRoom, value);
}
if(subject == "lightGarage") {
light(lightGarage, value);
}
if(subject == "blink") {
blink(100, valueString.toInt());
}
Serial.println(subject);
Serial.println(value);
}
Serial.print(message);
Serial.println();
delay(2000);
}
void light(int ledPin, boolean on) {
if(on) {
digitalWrite(ledPin, HIGH);
Serial.println("LED HIGH");
} else {
digitalWrite(ledPin, LOW);
Serial.println("led low");
}
}
void reset() {
Serial.println("Void reset");
light(lightRight, false);
light(lightRoom, false);
light(lightGarage, false);
}
void on() {
Serial.println("Void on");
light(lightRight, true);
light(lightRoom, true);
light(lightGarage, true);
}
void off() {
Serial.println("Void off");
light(lightRight, false);
light(lightRoom, false);
light(lightGarage, false);
}
void blink(int delayn, int count) {
for (int j=0; j <= count; j++){
on();
delay(delayn);
off();
delay(delayn);
}
}
That example expects the PubNub publish to be "lightRight:1" and not {"lightRight": "1"}.
I have the following code on my Arduino that constantly checks for a serial command that's sent over TCP using a Wifly library.
What the following code does is split a string like the following when sent over serial:
{power,tv}
It sets these properties accordingly:
char command[32];
char value[32];
It then executes certain methods using sendCommand(command, value); based on the properties set in the loop below.
Keep in mind this works just fine using the Wifly library.
void loop() {
Client client = server.available();
if (client) {
boolean start_data = false;
boolean next = false;
char command[32];
char value[32];
int index = 0;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.print(c);
if (c == '}') {
break;
}
if(start_data == true) {
if(c != ',') {
if(next)
value[index] = c;
else
command[index] = c;
index++;
} else {
next = true;
command[index] = '\0';
index = 0;
}
}
if (c == '{') {
start_data = true;
}
}
}
value[index] = '\0';
client.flush();
client.stop();
sendCommand(command,value);
}
}
Instead of using WiFi I've purchased some Xbee modules. They basically allow you to send serial bytes as well. The only problem is that I'm not quite sure how to handle the looping considering there's no while(client.connected()) anymore. Instead of that I've used while(Serial.available()) thinking that will work, but it doesn't set the value property for some reason.
I get command but I don't get value.
Also I'm not sure whether the loop above is the best way of doing what I'm after, all I know is that it works just fine the way it is. :)
Here is my new loop, which only returns command and not value for some reason:
void loop() {
// if there are bytes waiting on the serial port
if (Serial.available()) {
boolean start_data = false;
boolean next = false;
char command[32];
char value[32];
int index = 0;
while (Serial.available()) {
char c = Serial.read();
Serial.print(c);
if (c == '}') {
break;
}
if(start_data == true) {
if(c != ',') {
if(next)
value[index] = c;
else
command[index] = c;
index++;
} else {
next = true;
command[index] = '\0';
index = 0;
}
}
if (c == '{') {
start_data = true;
}
}
value[index] = '\0';
sendCommand(command,value);
}
}
If the following works with the new loop, I'll be very happy!
void sendCommand(char *command, char *value) {
// do something wonderful with command and value!
}
Got it working by using the following code:
#define SOP '{'
#define EOP '}'
bool started = false;
bool ended = false;
char inData[80];
byte index;
void setup()
{
Serial.begin(9600);
// Other stuff...
}
void loop()
{
// Read all serial data available, as fast as possible
while(Serial.available() > 0)
{
char inChar = Serial.read();
if(inChar == SOP)
{
index = 0;
inData[index] = '\0';
started = true;
ended = false;
}
else if(inChar == EOP)
{
ended = true;
break;
}
else
{
if(index < 79)
{
inData[index] = inChar;
index++;
inData[index] = '\0';
}
}
}
// We are here either because all pending serial
// data has been read OR because an end of
// packet marker arrived. Which is it?
if(started && ended)
{
// The end of packet marker arrived. Process the packet
char *cmd = strtok(inData, ",");
if(cmd)
{
char *val = strtok(NULL, ",");
if(val)
{
sendCommand(cmd, val);
}
}
// Reset for the next packet
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
}
I would change the structure similar to:
while( c != '}') {
if (Serial.available()) {
.
.
.
}
}
Serial characters are received significantly slower then the loop.
The program listen to messages from serial port in the form or where first character (A or D) means analog or digital, the 2nd character - pin, the 3rd character - 1/0 or from 0 to 255. The markers < and > show the beginning and the end of packet.
For example, if packet is received, the light is turned on by digitalWrite(13,1)
But nothing happens. When I send via serial monitor, for instance: light is supposed to blink but it does not. The same with analogue outputs.
bool started = false;
bool ended = false;
char inData[5];
byte index;
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0)
{
char inChar = Serial.read();
if (inChar == '<')
{
index = 0;
started = true;
ended = false;
}
else if (inChar == '>')
{
ended = true;
break;
}
else
{
if (index <= 4)
{
inData[index] = inChar;
index++;
}
}
if (started && ended)
{
if (inData[0] == 'A')
{
pinMode(inData[2],OUTPUT);
analogWrite(inData[2],inData[4]);
}
else if (inData[0] == 'D')
{
if (inData[4] == 1)
{
pinMode(inData[2],OUTPUT);
digitalWrite(inData[2],HIGH);
}
else if (inData[4] == 0)
{
pinMode(inData[2],OUTPUT);
digitalWrite(inData[2],LOW);
}
}
started = false;
ended = false;
index = 0;
}
}
Serial.println("Sending");
}
The following code will allow you to execute a method with an example serial string:
<power,led>
Once it processes this string, it'll execute the following method:
sendCommand(cmd, val);
See below for an example of how to turn on an LED on PIN 11.
#include <avr/pgmspace.h>
int IRledPin = 11;
#define SOP '<'
#define EOP '>'
bool started = false;
bool ended = false;
char inData[80];
byte index;
void setup() {
pinMode(IRledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
// Read all serial data available, as fast as possible
while (Serial.available() > 0) {
char inChar = Serial.read();
if (inChar == SOP) {
index = 0;
inData[index] = '\0';
started = true;
ended = false;
} else if (inChar == EOP) {
ended = true;
break;
} else {
if (index < 79) {
inData[index] = inChar;
index++;
inData[index] = '\0';
}
}
}
// We are here either because all pending serial
// data has been read OR because an end of
// packet marker arrived. Which is it?
if (started && ended) {
// The end of packet marker arrived. Process the packet
char *cmd = strtok(inData, ",");
if (cmd) {
char *val = strtok(NULL, ",");
if (val) {
sendCommand(cmd, val);
}
}
// Reset for the next packet
started = false;
ended = false;
index = 0;
inData[index] = '\0';
}
}
void sendCommand(char *command, char *value) {
if (strcmp(command,"power") == 0) {
power(value);
}
}
void power(char* value) {
if (strcmp(value, "led") == 0) {
digitalWrite(IRledPin, HIGH);
}
}
If the 2nd character is the pin, then you want inData[1] for your pin numbers instead of inData[2].
Why do you go from inData[0] to inData[2]? Wouldn't the second character be in inData[1]?
You're setting the pinMode to the actual value of inData[2]. That means to turn on pin 13, you need to send a carriage return character ('\r').
The code doesn't run below but it should help you to sort out your problem.
What it tries to do is split the inData into the Tokens[] array.
It then turns the ASCII data into integers with the atoi() statement.
Hope it helps.
Got the splitter from Segmentation Fault when using strtok_r
bool started = false;
bool ended = false;
char inData[5];
byte index;
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0)
{
char inChar = Serial.read();
if (inChar == '<')
{
index = 0;
started = true;
ended = false;
}
else if (inChar == '>')
{
ended = true;
break;
}
else
{
inData[index] = inChar;
index++;
}
if (started && ended)
{
// https://stackoverflow.com/questions/2227198/segmentation-fault-when-using-strtok-r
// Splint up input data
char *p = inData;
char *tokens[50];
int i = 0;
while (i < 50) {
tokens[i] = strtok_r(p, ",", &p);
if (tokens[i] == NULL) {
break;
}
i++;
}
if (tokens[0] == '<A')
{
pinMode(tokens[1],OUTPUT);
analogWrite(tokens[2],tokens[3]);
}
else if (token[0] == '<D')
{
if (atoi(token[3]) == 1)
{
pinMode(atoi(token[1]),OUTPUT);
digitalWrite(atoi(token[1]),HIGH);
}
else if (atoi(tokens[3]) == 0)
{
pinMode(atoi(tokens[1]),OUTPUT);
digitalWrite(atoi(tokens[1]),LOW);
}
}
started = false;
ended = false;
index = 0;
}
}