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 am running a simple web server (static IP) based on the default web server example, which is occasionally interrupted by an external input (eg. RFID reader) which sends data as a client to another server in the local network and starting the server again. the device runs as intended for a few days but then stops responding to pin inputs, accessing the server page seems to get it back on line (not sure about this) otherwise I am forced to manually reset when this happens.
Could using Serial Print(used during the debugging stage) without connecting a serial monitor be the issue?
test code:
/*
This program will decode the wiegand data from a HID RFID Reader (or, theoretically,
any other device that outputs weigand data).
The Wiegand interface has two data lines, DATA0 and DATA1. These lines are normally held
high at 5V. When a 0 is sent, DATA0 drops to 0V for a few us. When a 1 is sent, DATA1 drops
to 0V for a few us. There is usually a few ms between the pulses.
Your reader should have at least 4 connections (some readers have more). Connect the Red wire
to 5V. Connect the black to ground. Connect the green wire (DATA0) to Digital Pin 2 (INT0).
Connect the white wire (DATA1) to Digital Pin 3 (INT1). That's it!
Operation is simple - each of the data lines are connected to hardware interrupt lines. When
one drops low, an interrupt routine is called and some bits are flipped. After some time of
of not receiving any bits, the Arduino will decode the data.
*/
#include <Ethernet.h>
#include <SPI.h>
#include <EEPROM.h>
#define MAX_BITS 100 // max number of bits
#define WEIGAND_WAIT_TIME 3000 // time to wait for another weigand pulse.
unsigned char databits[MAX_BITS]; // stores all of the data bits
unsigned char bitCount; // number of bits currently captured
unsigned char flagDone; // goes low when data is currently being captured
unsigned int weigand_counter; // countdown until we assume there are no more bits
unsigned long facilityCode = 0; // decoded facility code
unsigned long cardCode = 0; // decoded card code
byte tr = 0; //testing trigger
byte ship[4]; //Home Center IP
byte wsip[4]; //Web Server IP
int scene[100]; //scene ID storage
//byte ptr = 0; //log pointer
byte ld = 0; //latest updated log
byte bc[20]; //Wiegand bitCount log
unsigned long wd[20]; //Wiegand data log
String readString1; //IP buffer
String tempstr = "{\r\n\"value\":\"";
String PostData = "{\r\n\"value\":\"1\"\r\n}"; //JSON data to send
// interrupt that happens when INTO goes low (0 bit)-2
void ISR_INT0()
{
Serial.print("0"); // uncomment this line to display raw binary
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
tr = 1;
}
// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1()
{
Serial.print("1"); // uncomment this line to display raw binary
if(bitCount<MAX_BITS)
databits[bitCount] = 1;
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
byte mac[] = { 0x00, 0xAB, 0xCB, 0xCD, 0xDE, 0x05 };
// byte ip[] = {192,168,4,101};
IPAddress ip(192, 168, 5, 211);
// byte gateway[] = {192,168,4,254};
// byte gateway[] = {192, 168, 5, 1};
// byte subnet[] = {255, 255, 255, 0};
// IPAddress server(192,168,4,100);
IPAddress sh(192, 168, 5, 65);
EthernetServer server(80); //server port arduino server will use
EthernetClient client;
char cnt1 = 0, cnt2 = 0;
void setup()
{
//pinMode(13, OUTPUT); // LED
pinMode(2, INPUT_PULLUP); // DATA0 (INT0)
pinMode(3, INPUT_PULLUP); // DATA1 (INT1)
Serial.begin(9600);
Serial.println("BioLite Net");
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
// binds the ISR functions to the falling edge of INTO and INT1
EEPROM.get(15, wsip);
IPAddress ip(wsip[0], wsip[1], wsip[2], wsip[3]);
net();
delay(10);
server.begin();
Serial.print(F("Web server is at "));
Serial.println(ip);
// Serial.print(F("server is at "));
// Serial.println(Ethernet.localIP());
EEPROM.get(10, ship);
IPAddress sh(ship[0], ship[1], ship[2], ship[3]);
Serial.print(F("Home Center is at "));
Serial.println(sh);
Serial.println(F("stored scenes are :"));
EEPROM.get(20, scene);
for (byte i = 0; i < 10 ; i++)
{
for (byte j = 0; j < 10 ; j++)
{
Serial.print((10 * i) + j);
Serial.print(" : ");
Serial.print(scene[(10 * i) + j]);
Serial.print(" ; ");
}
Serial.println();
}
EEPROM.get(310, bc);
EEPROM.get(330, wd);
EEPROM.get(305, ld);
byte temp = ld;
Serial.println(temp);
for (byte i = 0; i < 10 ; i++)
{
for (byte j = 0; j < 2 ; j++)
{
Serial.print(bc[temp]);
Serial.print(" : ");
Serial.print(wd[temp], BIN);
Serial.print(" ; ");
if (temp == 0)
temp = 20;
temp--;
}
Serial.println();
}
Serial.println();
/* temp = 19;
for (byte i = 0; i < 10 ; i++)
{
for (byte j = 0; j < 2 ; j++)
{
Serial.print(bc[temp]);
Serial.print(" : ");
Serial.print(wd[temp], BIN);
Serial.print(" ; ");
temp--;
if (temp < 0)
temp = 19;
}
Serial.println();
}*/
weigand_counter = WEIGAND_WAIT_TIME;
}
void loop()
{
// This waits to make sure that there have been no more data pulses before processing data
if (!flagDone) {
if (--weigand_counter == 0)
flagDone = 1;
}
// if we have bits and we the weigand counter went out
if (bitCount > 0 && flagDone) {
//if (tr == 1) {
tr == 0; delay(3000);
unsigned char i;
Serial.println();
if(bitCount>255) bitCount=255;
EEPROM.get(305, ld);
EEPROM.get(310, bc);
EEPROM.get(330, wd);
ld++;
if (ld > 19)
ld = 0;
Serial.println(ld);
// ptr += 5;
// ld = (ptr - 310) / 5;
bc[ld] = bitCount;
wd[ld] = 0;
for (i = 0; i < bitCount; i++)
{
Serial.print(databits[i]);
wd[ld] <<= 1;
wd[ld] |= databits[i];
}
EEPROM.put(305, ld);
EEPROM.put(310, bc);
EEPROM.put(330, wd);
Serial.println();
Serial.print("Read ");
Serial.print(bitCount);
Serial.print(" bits. ");
// we will decode the bits differently depending on how many bits we have
// see www.pagemac.com/azure/data_formats.php for mor info
if (bitCount == 35)
{
// 35 bit HID Corporate 1000 format
// facility code = bits 2 to 14
for (i = 2; i < 14; i++)
{
facilityCode <<= 1;
facilityCode |= databits[i];
}
// card code = bits 15 to 34
for (i = 14; i < 34; i++)
{
cardCode <<= 1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 37)
{
// HID 37 bit format H10304
// facility code = bits 2 to 17
for (i = 1; i < 17; i++)
{
facilityCode <<= 1;
facilityCode |= databits[i];
}
// card code = bits 18 to 36
for (i = 17; i < 36; i++)
{
cardCode <<= 1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 34)
{
// HID 34 bit format N1002
// facility code = bits 2 to 17
for (i = 1; i < 17; i++)
{
facilityCode <<= 1;
facilityCode |= databits[i];
}
// card code = bits 18 to 33
for (i = 17; i < 33; i++)
{
cardCode <<= 1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 26)
{
// standard 26 bit format H10301
// facility code = bits 2 to 9
for (i = 1; i < 9; i++)
{
facilityCode <<= 1;
facilityCode |= databits[i];
}
// card code = bits 10 to 25
for (i = 9; i < 25; i++)
{
cardCode <<= 1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 11)
{
// older Magstripe 11 bit format
// facility code = bits 6 to 9
for (i = 5; i < 9; i++)
{
facilityCode <<= 1;
facilityCode |= databits[i];
}
// card code = bits 1 to 5
for (i = 0; i < 5; i++)
{
cardCode <<= 1;
cardCode |= databits[i];
}
printBits();
}
else {
// you can add other formats if you want!
Serial.println("Unable to decode.");
}
EEPROM.get(10, ship);
IPAddress sh(ship[0], ship[1], ship[2], ship[3]);
EEPROM.get(20, scene);
String tempstr = "{\r\n\"value\":\"";
String PostData = "{\r\n\"value\":\"1\",\"invokeScenes\":true\r\n}"; //JSON data to send
tempstr = tempstr + cardCode;
PostData = tempstr + "\",\"invokeScenes\":true\r\n}";
if (client.connect(sh, 80)) {
client.print("GET /api/sceneControl?id=");
client.print(scene[cardCode]);
client.println("&action=start HTTP/1.1");
auth(sh);
Serial.print("Scene ");
Serial.print(scene[cardCode]);
Serial.println(" treggered");
/* }
if (Ethernet.begin(mac) == 0) {
Serial.println(F("Failed to configure Ethernet using DHCP"));
delay(3000);
Ethernet.begin(mac, ip);
if (Ethernet.localIP() != ip)
{
Serial.println(F("Failed to configure Ethernet using static IP"));
for (;;)
;
}
}
if (!client.connected())client.stop();
delay(1);
if (client.connect(sh, 80)) {*/
client.println("PUT /api/globalVariables/UID HTTP/1.1");
auth(sh);
Serial.print(cardCode);
Serial.println(" registered");
}
//if (!client.connected())client.stop();
while (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
// do nothing forevermore:
//while (true);
}
// cleanup and get ready for the next card
bitCount = 0;
facilityCode = 0;
cardCode = 0;
for (i = 0; i < MAX_BITS; i++)
{
databits[i] = 0;
}
delay(10);
net();
delay(10);
server.begin();
}
// Create a client connection
EthernetClient nclient = server.available();
if (nclient) {
Serial.println(F("new client"));
while (nclient.connected()) {
if (nclient.available()) {
/* char c = client.read();
Serial.write(c);
//read char by char HTTP request
if (readString1.length() < 100) {
//store characters to string
readString1 += c;
}*/
readString1 = nclient.readStringUntil('\n');
Serial.println(readString1);
//if HTTP request has ended– 0x0D is Carriage Return \n ASCII
// if (c == 0x0D) {
nclient.println("HTTP/1.1 200 OK"); //send new page
nclient.println("Content-Type: text/html");
nclient.println();
nclient.println(F("<HTML>"));
nclient.println(F("<HEAD>"));
nclient.println(F("<TITLE> Wegand to Home Center Configurator</TITLE>"));
nclient.println(F("</HEAD>"));
nclient.println(F("<BODY style=\"background-color:#F0F0FF; text-align: center;\">"));
nclient.println(F("<br>"));
nclient.println(F("<H1 style=\"color:LimeGreen;\">Wegand<span style=\"color:Teal;\">2</span><span style=\"color:Blue;\">HC</span></H1>"));
// client.println(F("<hr>"));
nclient.println(F("<br>"));
//nclient.println(F("<a style=\"color:SteelBlue;background-color:White;padding: 5px;\" href=\"/?TEST\"\">TEST</a><br /><br />"));
nclient.println(F("<form id=\"txt_form\" name=\"frmText\">"));
nclient.println(F("<H2 style=\"color:Crimson;\"><b>Configurator</b></H2>"));
nclient.println(F("<label style=\"color:DodgerBlue;\" for=\"code\">code : <input type=\"password\" id=\"code\" size=\"4\" maxlength=\"4\" value=\"0000\" /></label><br /><br />"));
nclient.println(F("<label style=\"color:DodgerBlue;\" for=\"hcip\">Home Center IP : <input type=\"text\" id=\"hcip\" size=\"15\" minlength=\"15\" maxlength=\"15\" value=\""));
if (ship[0] < 10)
{
nclient.print("00");
}
else if (ship[0] < 100)
{
nclient.print("0");
}
nclient.print(ship[0]);
nclient.print(F("."));
if (ship[1] < 10)
{
nclient.print("00");
}
else if (ship[1] < 100)
{
nclient.print("0");
}
nclient.print(ship[1]);
nclient.print(F("."));
if (ship[2] < 10)
{
nclient.print("00");
}
else if (ship[2] < 100)
{
nclient.print("0");
}
nclient.print(ship[2]);
nclient.print(F("."));
if (ship[3] < 10)
{
nclient.print("00");
}
else if (ship[3] < 100)
{
nclient.print("0");
}
nclient.print(ship[3]);
nclient.println(F("\" required></label><br /><br />"));
nclient.println(F("<label style=\"color:DodgerBlue;\" for=\"sip\">Web Server IP : <input type=\"text\" id=\"sip\" size=\"15\" minlength=\"15\" maxlength=\"15\" value=\""));
if (wsip[0] < 10)
{
nclient.print("00");
}
else if (wsip[0] < 100)
{
nclient.print("0");
}
nclient.print(wsip[0]);
nclient.print(F("."));
if (wsip[1] < 10)
{
nclient.print("00");
}
else if (wsip[1] < 100)
{
nclient.print("0");
}
nclient.print(wsip[1]);
nclient.print(F("."));
if (wsip[2] < 10)
{
nclient.print("00");
}
else if (wsip[2] < 100)
{
nclient.print("0");
}
nclient.print(wsip[2]);
nclient.print(F("."));
if (wsip[3] < 10)
{
nclient.print("00");
}
else if (wsip[3] < 100)
{
nclient.print("0");
}
nclient.print(wsip[3]);
nclient.println(F("\" readonly></label><br /><br />"));
nclient.println(F("<label style=\"color:DodgerBlue;\" for=\"uid\">User ID : <input type=\"text\" id=\"uid\" size=\"2\" maxlength=\"2\" autocomplete=\"on\" value=\"00\" /></label><br /><br />"));
nclient.println(F("<label style=\"color:DodgerBlue;\" for=\"sid\">Scene ID : <input type=\"text\" id=\"sid\" size=\"4\" maxlength=\"4\" autocomplete=\"on\" value=\"0000\" /></label><br /><br />"));
nclient.println(F("<a style=\"color:SteelBlue;background-color:White;padding: 5px;\" href=\"\" onclick=\"this.href='/?'+document.getElementById('code').value+document.getElementById('uid').value+document.getElementById('sid').value+document.getElementById('hcip').value+document.getElementById('sip').value\" >EDIT</a>"));
nclient.println(F("</form>"));
nclient.println(F("</BODY>"));
nclient.println(F("</HTML>"));
delay(10);
//stopping client
nclient.stop();
Serial.println(F("client disconnected"));
if (readString1.indexOf("?1729") == 5 && readString1.indexOf("HTTP/1.1") == 47) //checks code
{
Serial.println(F("pwd match"));
// readString1.toCharArray(url, 25);
Serial.println(readString1);
byte ad = readString1.substring(10, 12).toInt();
Serial.println(ad);
if (ad > 0 && ad < 100) {
scene[ad] = readString1.substring(12, 16).toInt();
Serial.println(scene[ad]);
}
else
Serial.println(F("invalid UID"));
byte p = 16;
for (byte i = 0; i < 4; i++) {
ship[i] = readString1.substring(p, p + 3).toInt();
p = p + 4;
}
p--;
for (byte i = 0; i < 4; i++) {
wsip[i] = readString1.substring(p, p + 3).toInt();
p = p + 4;
}
EEPROM.put(10, ship);
EEPROM.put(15, wsip);
EEPROM.put(20, scene);
delay(1500);
EEPROM.get(10, ship);
EEPROM.get(15, wsip);
EEPROM.get(20, scene);
//digitalWrite(5, HIGH);
//delay(1500);
//digitalWrite(5, LOW);
Serial.println(F("Edited"));
}
//clearing string for next read
readString1 = "";
// }
}
}
}
switch (Ethernet.maintain())
{
case 1:
//renewed fail
Serial.println(F("Error: renewed fail"));
break;
case 2:
//renewed success
Serial.println(F("Renewed success"));
//print your local IP address:
Serial.print(F("server is at "));
Serial.println(Ethernet.localIP());
break;
case 3:
//rebind fail
Serial.println(F("Error: rebind fail"));
break;
case 4:
//rebind success
Serial.println(F("Rebind success"));
//print your local IP address:
Serial.print(F("server is at "));
Serial.println(Ethernet.localIP());
break;
default:
//nothing happened
break;
}
}
void printBits()
{
// I really hope you can figure out what this function does
Serial.println();
Serial.print("FC = ");
Serial.print(facilityCode);
Serial.print(", CC = ");
Serial.println(cardCode);
}
void net()
{
if (Ethernet.begin(mac) == 0) {
Serial.println(F("Failed to configure Ethernet using DHCP"));
// if (Ethernet.hardwareStatus() == EthernetNoHardware) {
// Serial.println(F("Ethernet shield was not found. Sorry, can't run without hardware. :("));
// } else if (Ethernet.linkStatus() == LinkOFF) {
// Serial.println(F("Ethernet cable is not connected."));
// } else {
// Serial.println(F("No idea why"));
// }
delay(3000);
Ethernet.begin(mac, ip);
if (Ethernet.localIP() != ip)
{
Serial.println(F("Failed to configure Ethernet using static IP"));
for (;;)
;
}
}
Serial.print(F("server is at "));
Serial.println(Ethernet.localIP());
ip = Ethernet.localIP();
for (byte i = 0; i < 4; i++) {
wsip[i] = ip[i];
}
EEPROM.put(15, wsip);
}
void auth(IPAddress sh)
{
Serial.println(sh);
client.print("Host: ");
client.println(sh);
client.println("Authorization: Basic YmVuc2U6Qmlnc"); //need to insert base 64 user:password
client.print("Content-Length: ");
client.println(PostData.length());
client.println();
client.println(PostData);
}
I have to read the incoming SMS on my gsm module SIM900 (which is connected to Arduino), and I want to print the sender number and message on to serial monitor.
I first configure gsm module with AT commands and Response() function will give me the response to AT commands.
as any SMS will be in the following pattern
+CMT: "[Mobile number]", "[Date and Time]"
[message body]
So, I first extract +CMT and after that I will take mobile number and atlast we have message body. The code I have used is
char RcvdMsg[200] = "";
int RcvdCheck = 0;
int RcvdConf = 0;
int index = 0;
int RcvdEnd = 0;
char MsgMob[15];
char MsgTxt[50];
int MsgLength = 0;
void Config() // This function is configuring our SIM900 module i.e. sending the initial AT commands
{
delay(1000);
Serial.print("ATE0\r");
Response();
Serial.print("AT\r");
Response();
Serial.print("AT+CMGF=1\r");
Response();
Serial.print("AT+CNMI=1,2,0,0,0\r");
Response();
}
void setup()
{
Serial.begin(9600);
Config();
}
void loop()
{
RecSMS();
}
void Response() // Get the Response of each AT Command
{
int count = 0;
Serial.println();
while(1)
{
if(Serial.available())
{
char data =Serial.read();
if(data == 'K'){Serial.println("OK");break;}
if(data == 'R'){Serial.println("GSM Not Working");break;}
}
count++;
delay(10);
if(count == 1000){Serial.println("GSM not Found");break;}
}
}
void RecSMS() // Receiving the SMS and extracting the Sender Mobile number & Message Text
{
if(Serial.available())
{
char data = Serial.read();
if(data == '+'){RcvdCheck = 1;}
if((data == 'C') && (RcvdCheck == 1)){RcvdCheck = 2;}
if((data == 'M') && (RcvdCheck == 2)){RcvdCheck = 3;}
if((data == 'T') && (RcvdCheck == 3)){RcvdCheck = 4;}
if(RcvdCheck == 4){RcvdConf = 1; RcvdCheck = 0;}
if(RcvdConf == 1)
{
if(data == '\n'){RcvdEnd++;}
if(RcvdEnd == 3){RcvdEnd = 0;}
RcvdMsg[index] = data;
index++;
if(RcvdEnd == 2){RcvdConf = 0;MsgLength = index-2;index = 0;}
if(RcvdConf == 0)
{
Serial.print("Mobile Number is: ");
for(int x = 4;x < 17;x++)
{
MsgMob[x-4] = RcvdMsg[x];
Serial.print(MsgMob[x-4]);
}
Serial.println();
Serial.print("Message Text: ");
for(int x = 46; x < MsgLength; x++)
{
MsgTxt[x-46] = RcvdMsg[x];
Serial.print(MsgTxt[x-46]);
}
Serial.println();
Serial.flush();
}
}
}
}
The problem of the code is
After receiving first SMS I am getting my mobile number and message body. After that I am only getting sender number printed on to my serial monitor but not the message body.
Where It has gone wrong. I could not understood.
Please help me.......Thanks in advance.
If it does work the first time, but not subsequent times it probably has to do with some variables not being reset. You declare all of your variables at the top of the file even though they are only needed in the RecSMS() function. Try moving the declarations to the top of RecSMS().
void RecSMS() {
char RcvdMsg[200] = "";
int RcvdCheck = 0;
int RcvdConf = 0;
int index = 0;
int RcvdEnd = 0;
char MsgMob[15];
char MsgTxt[50];
int MsgLength = 0;
if(Serial.available()) {
// Rest of the code goes here
Thankyou #Michael. I think this also solves the issue.
The problem I found in the code is, we are not resetting all the variables in RecSMS function. So to solve this keep this below code before the Serial.flush() statement.
RcvdCheck = 0;
RcvdConf = 0;
index = 0;
RcvdEnd = 0;
MsgMob[15];
MsgTxt[50];
MsgLength = 0;
This will solve the problem
I had purchased a microSD card shield from sparkfun and I wish to do data logging to read 2 MPU6050. I wished to have sampling frequency of 100Hz, so I came across one example from Greiman about lowlatencylogger. Using his example and SDFat library instead of SD library, I do can get very good sampling frequency, however, I cannot terminate the data logging at will.
I tried to add a switch to set a condition where if the arduino read the switch, then it will start truncating the file. But so far no result. So can anyone help me??
the code that I am using
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
//------------------------------------------------------------------------------
// User data functions. Modify these functions for your data items.
#include "UserDataType.h" // Edit this include file to change data_t.
MPU6050 mpu;
MPU6050 mpu_69 (0x69);
int switchPin = 6;
void setupData() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
// set I2C 400 kHz
TWBR = (F_CPU/400000 - 16)/2;
Serial.println(F("Using Wire"));
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
Serial.println(F("Using Fastwire"));
#endif
mpu.initialize();
mpu_69.initialize();
pinMode(switchPin,INPUT_PULLUP);
}
// Acquire a data record.
void acquireData(data_t* data) {
data->time = micros();
data->hs = analogRead(0);
data->to = analogRead(1);
mpu.getMotion6(&data->axr, &data->ayr, &data->azr,
&data->gxr, &data->gyr, &data->gzr);
mpu_69.getMotion6(&data->axl, &data->ayl, &data->azl,
&data->gxl, &data->gyl, &data->gzl);
}
// Print a data record.
void printData(Print* pr, data_t* data) {
pr->print(data->time);
pr->write(',');
pr->print(data->hs);
pr->write(',');
pr->print(data->to);
pr->write(',');
pr->print(data->axr);
pr->write(',');
pr->print(data->ayr);
pr->write(',');
pr->print(data->azr);
pr->write(',');
pr->print(data->gxr);
pr->write(',');
pr->print(data->gyr);
pr->write(',');
pr->print(data->gzr);
pr->write(',');
pr->print(data->axl);
pr->write(',');
pr->print(data->ayl);
pr->write(',');
pr->print(data->azl);
pr->write(',');
pr->print(data->gxl);
pr->write(',');
pr->print(data->gyl);
pr->write(',');
pr->println(data->gzl);
}
// Print data header.
void printHeader(Print* pr) {
pr->println(F("micros,heels,toeo,axshank,ayshank,azshank,gxshank,gyshank,gzshank,axankle,ayankle,azankle,gxankle,gyankle,gzankle"));
}
//==============================================================================
// Start of configuration constants.
//==============================================================================
//Interval between data records in microseconds.
const uint32_t LOG_INTERVAL_USEC = 10000;
//------------------------------------------------------------------------------
// Pin definitions.
//
// SD chip select pin.
const uint8_t SD_CS_PIN = 8;
//
// Digital pin to indicate an error, set to -1 if not used.
// The led blinks for fatal errors. The led goes on solid for SD write
// overrun errors and logging continues.
const int8_t ERROR_LED_PIN = -1;
//------------------------------------------------------------------------------
// File definitions.
//
// Maxrimum file size in blocks.
// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks.
// This file is flash erased using special SD commands. The file will be
// truncated if logging is stopped early.
const uint32_t FILE_BLOCK_COUNT = 256000;
////////////////////////////
uint32_t const ERASE_SIZE = 262144L;
void logData() {
unsigned long timeout =0;
bool truncate=false;
uint32_t bgnBlock, endBlock;
// Allocate extra buffer space.
block_t block[BUFFER_BLOCK_COUNT];
block_t* curBlock = 0;
Serial.println();
// Find unused file name.
if (BASE_NAME_SIZE > 6) {
error("FILE_BASE_NAME too long");
}
while (sd.exists(binName)) {
if (binName[BASE_NAME_SIZE + 1] != '9') {
binName[BASE_NAME_SIZE + 1]++;
} else {
binName[BASE_NAME_SIZE + 1] = '0';
if (binName[BASE_NAME_SIZE] == '9') {
error("Can't create file name");
}
binName[BASE_NAME_SIZE]++;
}
}
// Delete old tmp file.
if (sd.exists(TMP_FILE_NAME)) {
Serial.println(F("Deleting tmp file"));
if (!sd.remove(TMP_FILE_NAME)) {
error("Can't remove tmp file");
}
}
// Create new file.
Serial.println(F("Creating new file"));
binFile.close();
if (!binFile.createContiguous(sd.vwd(),
TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) {
error("createContiguous failed");
}
// Get the address of the file on the SD.
if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
error("contiguousRange failed");
}
// Use SdFat's internal buffer.
uint8_t* cache = (uint8_t*)sd.vol()->cacheClear();
if (cache == 0) {
error("cacheClear failed");
}
// Flash erase all data in the file.
Serial.println(F("Erasing all data"));
uint32_t bgnErase = bgnBlock;
uint32_t endErase;
while (bgnErase < endBlock) {
endErase = bgnErase + ERASE_SIZE;
if (endErase > endBlock) {
endErase = endBlock;
}
if (!sd.card()->erase(bgnErase, endErase)) {
error("erase failed");
}
bgnErase = endErase + 1;
}
// Start a multiple block write.
if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) {
error("writeBegin failed");
}
// Initialize queues.
emptyHead = emptyTail = 0;
fullHead = fullTail = 0;
// Use SdFat buffer for one block.
emptyQueue[emptyHead] = (block_t*)cache;
emptyHead = queueNext(emptyHead);
// Put rest of buffers in the empty queue.
for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) {
emptyQueue[emptyHead] = &block[i];
emptyHead = queueNext(emptyHead);
}
// Wait for Serial Idle.
Serial.flush();
delay(10);
uint32_t bn = 0;
uint32_t t0 = millis();
uint32_t t1 = t0;
uint32_t overrun = 0;
uint32_t overrunTotal = 0;
uint32_t count = 0;
uint32_t maxlatency = 0;
int32_t diff;
// Start at a multiple of interval.
uint32_t logTime = micros()/LOG_INTERVAL_USEC + 1;
logTime *= LOG_INTERVAL_USEC;
bool closeFile = false;
while (1) {
// Time for next data record.
logTime += LOG_INTERVAL_USEC;
if (Serial.available()) {
closeFile = true;
}
if (closeFile) {
if (curBlock != 0 && curBlock->count >= 0) {
// Put buffer in full queue.
fullQueue[fullHead] = curBlock;
fullHead = queueNext(fullHead);
curBlock = 0;
}
} else {
if (curBlock == 0 && emptyTail != emptyHead) {
curBlock = emptyQueue[emptyTail];
emptyTail = queueNext(emptyTail);
curBlock->count = 0;
curBlock->overrun = overrun;
overrun = 0;
}
do {
diff = logTime - micros();
} while(diff > 0);
if (diff < -10) {
error("LOG_INTERVAL_USEC too small");
}
if (curBlock == 0) {
overrun++;
} else {
acquireData(&curBlock->data[curBlock->count++]);
if (curBlock->count == DATA_DIM) {
fullQueue[fullHead] = curBlock;
fullHead = queueNext(fullHead);
curBlock = 0;
}
}
}
if (fullHead == fullTail) {
// Exit loop if done.
if (closeFile) {
break;
}
} else if (!sd.card()->isBusy()) {
// Get address of block to write.
block_t* pBlock = fullQueue[fullTail];
fullTail = queueNext(fullTail);
// Write block to SD.
uint32_t usec = micros();
if (!sd.card()->writeData((uint8_t*)pBlock)) {
error("write data failed");
}
usec = micros() - usec;
t1 = millis();
if (usec > maxlatency) {
maxlatency = usec;
}
count += pBlock->count;
// Add overruns and possibly light LED.
if (pBlock->overrun) {
overrunTotal += pBlock->overrun;
if (ERROR_LED_PIN >= 0) {
digitalWrite(ERROR_LED_PIN, HIGH);
}
}
// Move block to empty queue.
emptyQueue[emptyHead] = pBlock;
emptyHead = queueNext(emptyHead);
bn++;
if (bn == FILE_BLOCK_COUNT) {
// File full so stop
break;
}
}
}
if (!sd.card()->writeStop()) {
error("writeStop failed");
}
do{
if(digitalRead(switchPin)==LOW){
if(millis()>timeout){ // switchPin is low and has been low for 100ms
truncate = true; // close the file,
// truncate at current record number,
// rename to 'binname'
}
}
else { // switchPin High, not pressed
timeout = millis() + 100; // time that switch has to be pressed to be valid
}
}while(truncate=false);
if(truncate == true){
// Truncate file if recording stopped early.
if (bn != FILE_BLOCK_COUNT) {
//Serial.println(F("Truncating file"));
if (!binFile.truncate(512L * bn)) {
error("Can't truncate file");
}
}
}
binFile.close();
if (!binFile.rename(sd.vwd(), binName)) {
error("Can't rename file");
}
}
//------------------------------------------------------------------------------
void setup(void) {
if (ERROR_LED_PIN >= 0) {
pinMode(ERROR_LED_PIN, OUTPUT);
}
Serial.begin(38400);
sd.begin(38400);
while (!Serial) {}
pinMode(switchPin,INPUT_PULLUP);
Serial.print(F("FreeRam: "));
Serial.println(FreeRam());
Serial.print(F("Records/block: "));
Serial.println(DATA_DIM);
if (sizeof(block_t) != 512) {
error("Invalid block size");
}
setupData();
// initialize file system.
if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
sd.initErrorPrint();
fatalBlink();
}
}
//------------------------------------------------------------------------------
void loop(void) {
logData();
binaryToCsv();
}
You need to modify the following code segment:
if (Serial.available()) {
closeFile = true;
}
To be something like:
if (Serial.available() || (stopSwitch(haltPIN) == LOW)) {
closeFile = true;
}
Where stopSwitch is normally HIGH connected to haltPIN
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;
}
}