Related
I'm searching the answer for a while but haven't found how to fix this problem. I have a lot of neopixel animations (currently 50 of them), these are written with delays which keeps the animations simple and readable. disadvantage is the delays as you all know. 50 animations to rewrite is a hell of a job so I want to avoid this. What I did is bought an ESP32 with two cores, so I thought I could run the animations on one core and the webserver on one core. previously I wanted to do I with an interrupt on a ESP8266 but I red and tested that I was not possible to do communication things or run a webserver in an interrupt for example. Is it possible to do that with two cores on an ESP32 or am I running in to the same problem as earlier? current output of the program: My webserver starts and the neopixel animation is showed when pushing the button, however my webserver continuously restarts over and over again. Any help appreciated, thanks in advance!
ps: In the worst case scenario I have to rewrite my animations, anyone an idea how to replace 3 for loops in to non blocking code?
code running on ESP32:
TaskHandle_t Task1;
TaskHandle_t Task2;
#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 24
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
for(uint16_t i=0; i<NUM_LEDS; i++) {
setPixel(i, red, green, blue);
showStrip();
delay(SpeedDelay);
}
}
// *** REPLACE TO HERE ***
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
FastLED.show();
#endif
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
#endif
}
void setAll(byte red, byte green, byte blue) {
for(int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}
#include <WiFi.h>
const char* WIFI_NAME= "xxxxxxxxxx";
const char* WIFI_PASSWORD = "xxxxxxxxxx";
WiFiServer server(80);
String header;
// Auxiliary variables to store the current output state
String output5State = "off";
String output4State = "off";
// Assign output variables to GPIO pins
const int output5 = 2;
const int output4 = 4;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
String ledState = "off";
void setup() {
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// Set outputs to LOW
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
}
//Task1code: blinks an LED every 1000 ms
void Task1code( void * pvParameters ){
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
strip.begin();
strip.show(); // Initialize all pixels to 'off'
for(;;){
/*
digitalWrite(output5, HIGH);
delay(1000);
digitalWrite(output5, LOW);
delay(1000);*/
//Serial.print("state:" + ledState);
if(ledState == "on") {
//digitalWrite(output4, HIGH);
colorWipe(0x00,0xff,0x00, 50);
colorWipe(0x00,0x00,0x00, 50);
} else {
strip.clear();
strip.show();
}
}
}
//Task2code: blinks an LED every 700 ms
void Task2code( void * pvParameters ){
Serial.print("Connecting to ");
Serial.println(WIFI_NAME);
WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print("Trying to connect to Wifi Network");
}
Serial.println("");
Serial.println("Successfully connected to WiFi network");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
for(;;){
WiFiClient client = server.available();
if (client) {
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// turns the GPIOs on and off
if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
//digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
//digitalWrite(output5, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
ledState = "on";
//digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
ledState = "off";
//digitalWrite(output4, LOW);
}
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP8266 Web Server</h1>");
// Display current state, and ON/OFF buttons for GPIO 5
client.println("<p>GPIO 5 - State " + output5State + "</p>");
// If the output5State is off, it displays the ON button
if (output5State=="off") {
client.println("<p><button class=\"button\">ON</button></p>");
} else {
client.println("<p><button class=\"button button2\">OFF</button></p>");
}
// Display current state, and ON/OFF buttons for GPIO 4
client.println("<p>GPIO 4 - State " + output4State + "</p>");
// If the output4State is off, it displays the ON button
if (output4State=="off") {
client.println("<p><button class=\"button\">ON</button></p>");
} else {
client.println("<p><button class=\"button button2\">OFF</button></p>");
}
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
}
void loop(){
}
animation with three for loops:
void theaterChaseRainbow(int SpeedDelay) { /* for wheel watch higher in the code */
byte *c;
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (int i=0; i < NUM_LEDS; i=i+3) {
c = Wheels( (i+j) % 255);
setPixel(i+q, *c, *(c+1), *(c+2)); //turn every third pixel on
}
showStrip();
delay(SpeedDelay);
for (int i=0; i < NUM_LEDS; i=i+3) {
setPixel(i+q, 0,0,0); //turn every third pixel off
}
}
}
}
You're 95% of the way there. ESP32 runs FreeRTOS with preemptive multi-threading. Your code is quite reasonably divided into two threads (Task1 and Task2) which run on different cores. In fact, the number of cores doesn't really matter much as long as you're not running out of CPU cycles or violating the real-time deadlines of your animations. You could probably run both tasks concurrently on a single core without the ESP32 breaking a sweat.
As for the HTTP server restarting - that's the intended behaviour of your code, is it not? The (rather horribly indented) function Task2code runs a never-ending loop which starts the HTTP server, serves a page and the stops. Is this loop really necessary?
I'm trying Sim800l and ESP8066 As my serial communication to Mega r3.
when i try sim800l code side, something like this: which i refined the code a little bit. In Serial monitor handshakes are ok. but when new sms arrives it doesn't show the right content.
Why with same code I see different results?
void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
Serial.println("Starting...");
delay(1000);
Serial1.println("AT");
pollSms();
Serial1.println("AT+CMGF=1");
pollSms();
Serial1.println("AT+CNMI=1,2,0,0,0");
pollSms();
}
void loop()
{
pollSms();
}
void pollSms()
{
delay(500);
while (Serial.available())
{
Serial1.write(Serial.read());
}
while(Serial1.available())
{
Serial.write(Serial1.read());
}
}
everything is just fine but when I try
#include <SPI.h>//Communicate via WiFi
#include <DHT.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <WiFi.h>
/* Libraries */
/* Variables */
char id[] = "id";//id of Wifi network
char pass[] = "password";//password of Wifi network
const char* host = "esp8266sd";
float humadity1 , temprature1=25;//Solon 1
float humadity2 , temprature2;//Solon 2
int Soil_humadity1,Soil_humadity2,Soil_humadity3;
char c;
String WiFi_instruction="";
String SMSmessage="";
String number, Answer;
boolean valid;
#define TWO_HRS 7200000
unsigned long startTime1,startTime2;
/* Variables */
/* AM2301 */
#define DHTTYPE DHT21 // It defines which kind of humadity and temprature sensor is connecter (AM2301)
DHT dht1(DHTPIN1, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);
/* AM2301 */
/* Android App */
WiFiServer server(80);
/* Android App */
/* Valid numbers */
String num1="9016057005";
String num2="9026057005";//change it
/* Valid numbers */
void setup()
{
/* Pins Settings */
/* Serial communications */
Serial.begin(9600); // setup baudrate for transition to "serial monitor"
Serial1.begin(9600);//Sim800l Serial Communication
Serial3.begin(9600);//ESP8266 Serial Communication
/* SMS Settings */
Serial.println("Start!...");
Serial1.println("AT"); //Send AT command it will says "OK" if everything is fine
Serialcom(); //description below
Serial1.println("AT+CMGF=0"); // Configuring TEXT mode
Serialcom();
Serial1.println("AT+IPR=9600");
Serial1.println("AT+CNMI=1,2,0,0,0");
Serialcom();
/* SMS Settings */
/* Serial communications */
/* Timers */
startTime1 = millis();
startTime2 = millis();
/* Timers */
/* Sensors */
dht1.begin(); //setup humadity and temprature sensor: Solon 1
dht2.begin(); //setup humadity and temprature sensor: Solon 2
humadity1 = dht1.readHumidity();
temprature1 = dht1.readTemperature();
humadity2 = dht2.readHumidity();
temprature2 = dht2.readTemperature();
/* Sensors */
}//setup ended
void loop()
{
char x;
/* Receiving instruction from WiFi' serial */
while (Serial3.available())
{
x=Serial3.read();
WiFi_instruction.concat(x);
}
Serial.println("WiFi instructions");
/* Check for any instruction*/
WiFi_instruction="";// WiFi_instruction is empty now.
}//if WiFi_instruction.length()!-0
/* Receiving instruction from WiFi' serial */
/* Yl-69 Sensors */
Soil_humadity1=digitalRead(YL1);//If it return 1, soil is ok otherwise not
Soil_humadity2=digitalRead(YL2);
Soil_humadity3=digitalRead(YL3);
/* Yl-69 Sensors */
/* AS2301 Sensors's Data */
float temp_temprature1,temp_temprature2,temp_humadity1,temp_humadity2;
temp_temprature1= dht1.readTemperature();
temp_temprature2= dht2.readTemperature();
temp_humadity1=dht1.readHumidity();
temp_humadity2=dht2.readHumidity();
//Whether data is NaN or 0 or some none sense increment-decrement, new numbers won't be considered
if(isnan(temp_temprature1) ||isnan(temp_temprature2)||
isnan(temp_humadity1)||isnan(temp_humadity2))
{
/* Do nothing */
}
else
{
if(temp_temprature1!=0 &&
temp_temprature2!=0&&
temp_humadity1!=0 &&
temp_humadity2!=0)
{
if(abs(dht1.readHumidity()-humadity1)<10
&& abs(dht2.readHumidity()-humadity2)<10
&& abs(dht1.readTemperature()-temprature1)<10
&& abs(dht2.readTemperature()-temprature2)<10)
{
Serial.print(" Sensor values have been changed ");
humadity1 = dht1.readHumidity();
temprature1 = dht1.readTemperature();
humadity2 = dht2.readHumidity();
temprature2 = dht2.readTemperature();
}
}
}
/* AS2301 Sensors's Data */
/* Check for any SMS */
while(Serial1.available())
{
x=Serial1.read();
SMSmessage.concat(x);
}
Serial.println("SMS:");
Serial.println(SMSmessage);
if(SMSmessage.length()>0)
{
int valid1=SMSmessage.indexOf(num1);
int valid2=SMSmessage.indexOf(num2);
if(valid1==0 || valid2==0)
{
Serial.println("number is valid");
valid=true;
}
/*Extranct the number to andwer */
if(valid1==0)
number=num1;
if(valid2==0)
number=num2;
/*Extranct the number to andwer */
/*Check for any sms */
/* Answering via SMS */
//If there is the Code for a specific Instruction it return 1 otherwise returns -1
if(valid)
{
inst00=SMSmessage.indexOf(inst0);
inst01_CHECK=SMSinst01=SMSmessage.indexOf(inst1);//automatic
inst02_CHECK=SMSinst02=SMSmessage.indexOf(inst2);
inst03_CHECK=SMSinst03=SMSmessage.indexOf(inst3);
inst04_CHECK=SMSinst04=SMSmessage.indexOf(inst4);
if(SMSinst02 ==-1 && SMSinst03==-1 && SMSinst04==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst01=0;
inst05_CHECK=SMSinst05=SMSmessage.indexOf(inst5);//automatic
inst06_CHECK=SMSinst06=SMSmessage.indexOf(inst6);
inst07_CHECK=SMSinst07=SMSmessage.indexOf(inst7);
inst08_CHECK=SMSinst08=SMSmessage.indexOf(inst8);
if(SMSinst06 ==-1 && SMSinst07==-1 && SMSinst08==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst05=0;
inst09_CHECK=SMSinst09=SMSmessage.indexOf(inst9);//automatic
inst010_CHECK=SMSinst010=SMSmessage.indexOf(inst10);
inst011_CHECK=SMSinst011=SMSmessage.indexOf(inst11);
if(SMSinst010 ==-1 && SMSinst011==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst09=0;
inst012_CHECK=SMSinst012=SMSmessage.indexOf(inst12);//automatic
inst013_CHECK=SMSinst013=SMSmessage.indexOf(inst13);
inst014_CHECK=SMSinst014=SMSmessage.indexOf(inst14);
if(SMSinst013 ==-1 && SMSinst014==-1)// if none of the non-automatic in selected it mast remain automatic
inst012=0;
inst015_CHECK=SMSinst015=SMSmessage.indexOf(inst15);//automatic
inst016_CHECK=SMSinst016=SMSmessage.indexOf(inst16);
inst017_CHECK=SMSinst017=SMSmessage.indexOf(inst17);
if(SMSinst016 ==-1 && SMSinst017==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst015=0;
inst018_CHECK=SMSinst018=SMSmessage.indexOf(inst18);//automatic
inst019_CHECK=SMSinst019=SMSmessage.indexOf(inst19);
inst020_CHECK=SMSinst020=SMSmessage.indexOf(inst20);
if(SMSinst019 ==-1 && SMSinst020==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst018=0;
inst021_CHECK=SMSinst021=SMSmessage.indexOf(inst21);//automatic
inst022_CHECK=SMSinst022=SMSmessage.indexOf(inst22);
inst023_CHECK=SMSinst023=SMSmessage.indexOf(inst23);
if(SMSinst022 ==-1 && SMSinst023==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst021=0;
inst024_CHECK=SMSinst024=SMSmessage.indexOf(inst24);//automatic
inst025_CHECK=SMSinst025=SMSmessage.indexOf(inst25);
inst026_CHECK=SMSinst026=SMSmessage.indexOf(inst26);
if(SMSinst025 ==-1 && SMSinst026==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst024=0;
inst027_CHECK=SMSinst027=SMSmessage.indexOf(inst27);//automatic
inst028_CHECK=SMSinst028=SMSmessage.indexOf(inst28);
inst029_CHECK=SMSinst029=SMSmessage.indexOf(inst29);
if(SMSinst028 ==-1 && SMSinst029==-1)// if none of the non-automatic in selected it mast remain automatic
SMSinst027=0;
SMSmessage="";//SMSmessage now is empty until next sms
}//if valid
}// if SMS.length()
Serial.println("SMS instructions");
if(inst00)
{
String statSoil1,statSoil2,statSoil3;
/* YL, Soil's humadity Sensors results */
}//Loop ends
/*Functions */
/*
void Serialcom()
{
delay(500);
while(Serial.available()) // IDE serial l serial Serial1
{
Serial1.write(Serial.read());//Forward what Serial received to Software Serial Port
}
while(Serial1.available()) //serialSerial1 l serial dial IDE
{
Serial.write(Serial1.read());//Forward what Software Serial received to Serial Port
}
}
/*Functions */
I'm using an 125Khz RFID module RDM6300 with arduino nano.
While the card is near the RFID reader the loop will read the card multiple times. I want it to read only once while the card is near the reader then read it again if a new connection is being made.
*This code is not writen by me, this is the source:
https://github.com/Wookai/arduino-rfid
// define constants for pins
//int SUCCESS = 10;
//int ERROR = 13;
// variables to keep state
int readVal = 0; // individual character read from serial
unsigned int readData[10]; // data read from serial
int counter = -1; // counter to keep position in the buffer
char tagId[11]; // final tag ID converted to a string
char* authorizedTags[4]; // array to hold the list of authorized tags
// fills the list of authorzied tags
void initAuthorizedTags() {
// add your own tag IDs here
authorizedTags[0] = "0400680B85";
authorizedTags[1] = "0400063EB9";
authorizedTags[2] = "040004F3F5";
authorizedTags[3] = "04006813AB";
}
void setup() {
Serial.begin(9600);
// pinMode(SUCCESS, OUTPUT);
//pinMode(ERROR, OUTPUT);
initAuthorizedTags();
}
// check if the tag ID we just read is any of the authorized tags
int checkTag() {
int i;
for (i = 0; i < 4; ++i) {
if (strcmp(authorizedTags[i], tagId) == 0) {
return 1;
}
}
return 0;
}
// convert the int values read from serial to ASCII chars
void parseTag() {
int i;
for (i = 0; i < 10; ++i) {
tagId[i] = readData[i];
}
tagId[10] = 0;
}
// once a whole tag is read, process it
void processTag() {
// convert id to a string
parseTag();
// print it
printTag();
// check if the tag is authorized
if (checkTag() == 1) {
tagSuccess(); // if so, perform an action (blink a led, open a door, etc...)
} else {
tagFailed(); // otherwise, inform user of failure
}
}
void printTag() {
Serial.print("Tag value: ");
Serial.println(tagId);
}
// perform an action when an authorized tag was read
void tagSuccess() {
Serial.println("Tag authorized.");
// here, we simply turn on the success LED for 2s
// digitalWrite(SUCCESS, HIGH);
//digitalWrite(ERROR, LOW);
// delay(2000);
}
// inform the user that the tag is not authorized
void tagFailed() {
Serial.println("Unauthorized access!");
//digitalWrite(SUCCESS, LOW);
// digitalWrite(ERROR, HIGH);
// delay(2000);
}
// this function clears the rest of data on the serial, to prevent multiple scans
void clearSerial() {
while (Serial.read() >= 0) {
; // do nothing
}
}
void loop() {
// turn LEDs off
// digitalWrite(SUCCESS, LOW);
// digitalWrite(ERROR, LOW);
if (Serial.available() > 0) {
// read the incoming byte:
readVal = Serial.read();
// a "2" signals the beginning of a tag
if (readVal == 2) {
counter = 0; // start reading
}
// a "3" signals the end of a tag
else if (readVal == 3) {
// process the tag we just read
processTag();
// clear serial to prevent multiple reads
clearSerial();
// reset reading state
counter = -1;
}
// if we are in the middle of reading a tag
else if (counter >= 0) {
// save valuee
readData[counter] = readVal;
// increment counter
++counter;
}
}
}
Thank you.
Thank you for your answers. I tried to accept the multiple reads and print only one but it keeps printing "already read" instead of reading the card first time, this is the code:
void printTag() {
if(strcmp(tagId,previous)==1){
strcpy(previous, tagId);
Serial.print("Tag value: ");
Serial.println(tagId);
}
else
{
Serial.print("already read");
}
}
I also tried to put the delay after end of tag but it still reads the card multiple times.
I tried another code, it still reads the tag multiple times.
#include <SoftwareSerial.h>
// RFID | Nano
// Pin 1 | D2
// Pin 2 | D3
SoftwareSerial Rfid = SoftwareSerial(2,3);
int timer=0;
int reference = 1000;
int card_status = 0;
void setup() {
// Serial Monitor to see results on the computer
Serial.begin(9600);
// Communication to the RFID reader
Rfid.begin(9600);
}
void read() {
// check, if any data is available
// as long as there is data available...
while(Rfid.available() > 0 ){
// read a byte
int r = Rfid.read();
// print it to the serial monitor
Serial.print(r, DEC);
Serial.print(" ");
}
// linebreak
Serial.println();
timer=0;
}
void loop()
{
if((Rfid.available() > 0 ) && (card_status == 0) )
{
read();
}
if((!Rfid.available() > 0 ) && (card_status == 1) )
{
card_status=0;
}
}
I'm sorry for the late response. I forgot about this topic.
I solved the problem by making the arduino wait for a response after writing the RFID code for the frist time.
I was able to do that because my arduino was sending the code to a C# application via serial port.
Here is how it works: the arduino prints the RFID code on the serial, from there it is picked up by the C# application which searches a database to see if the code is stored there. Depending on the result, the application prints a character('y' or 'n') which is picked up by the arduino. Depending on the character recieved, the arduino lights up a led ( green or red) and makes a noise. Now a new RFID reading can be made.
Here is the code:
#include <SoftwareSerial.h>
#include "RDM6300.h"
SoftwareSerial rdm_serial(8, 9);
RDM6300<SoftwareSerial> rdm(&rdm_serial);
String comanda;
char c="";
int led_verde = 2;
int led_rosu = 7;
int buzzer = 12;
int i;
void buzz(int n = 1)
{
for (int i = 0; i < n; i++) {
digitalWrite(buzzer, LOW);
delay(200);
digitalWrite(buzzer, HIGH);
delay(200);
}
}
void ledVerde()
{
digitalWrite(led_verde, HIGH);
buzz(1);
delay(1000);
digitalWrite(led_verde, LOW);
}
void ledRosu()
{
digitalWrite(led_rosu, HIGH);
buzz(3);
delay(1000);
digitalWrite(led_rosu, LOW);
}
void setup()
{
pinMode(led_verde, OUTPUT);
pinMode(led_rosu, OUTPUT);
pinMode(buzzer, OUTPUT);
digitalWrite(led_verde, LOW);
digitalWrite(led_rosu, LOW);
digitalWrite(buzzer, HIGH);
Serial.begin(9600);
}
void loop()
{
static unsigned long long last_id = 0;
last_id = rdm.read();
rdm.print_int64(last_id);
Serial.println();
rdm_serial.end();
Serial.flush();
while(!Serial.available());
c=Serial.read();
if(c=='y')
{
ledVerde();
c="";
}
if(c=='n')
{
ledRosu();
}
Serial.flush();
last_id="";
c="";
rdm_serial.begin(9600);
}
You can find the RDM6300 library here: https://github.com/arliones/RDM6300-Arduino
Long time passed the original question, but maybe my answer would be useful for future visitors.
The RDM6300 works by:
automatically reading the data, and then
your code transfers the read data to the buffer for further processing.
Imagine it as a Baggage carousel in the airport. There are multiple luggage (data) on the carousel (reader), and you pick them one by one (transferring to buffer).
So, the problem of multiple reads, is that you have got read data in the reader (luggage on the carousel), that your code is gradually transferring them to the buffer (picking the luggage up).
In our example, if you don't like to collect all luggage, you can ask someone to take some of them, before they reach to you.
The below code does this. While you have data in the reader (the card is near to the reader), it transfers data from reader to buffer and then zeros all of them in the buffer:
First, place this code before "void setup()":
boolean multipleRead = false;
This defines a false/true variable to tell if this is the first time you are reading the tag (false), or it's being read multiple times (true).
Then, put this one at the end of the code block that shows the tag is fully read. If you are using Michael Schoeffler's library for your RDM6300/630 RFID, put it after "else if (ssvalue == 3) {":
multipleRead = true;
It change the variable to true, when your tag is read. That tells the program that your first read is done and the next upcoming read(s) would be "multiple read" and you don't want them.
Then put this at the end of the RFID reader code (if your RFID code is under void loop (), put the below code just after "void loop (){":
if (multipleRead) {
while (ssrfid.available() > 0) {
int ssvalue = ssrfid.read(); // read
if (ssvalue == -1) { // no data was read
break;
}
}
for (int x = 0; x < 14; x++)
{
buffer[x] = 0;
}
multipleRead = false;
}
It empties the reader and then zeros the buffer, while there is a card nearby. When you move the card away, multipleRead value would turn to false, which let another RFID reading loop to initiate.
Hope that helped :)
I guess what you want is a edge trigger instead of level trigger with time limit.
For example, you may prefer to read a RFID card when it firstly comes near to the antenna, once only; when it keeps to contact the antenna, still take no more actions. When you remove the card and place it again near to the antenna, the MCU starts to read the card again.
If so, the following code could be for your reference. What I have done is just to add 1 more flag to keep checking the card_status before checking if a RFID card comes near to the antenna.
int card_status = 0; //0:readable; 1:not-readable
if ( (Serial.available() > 0) && (card_status == 0) ) {
card_status = 1; //disable to read card after exit this loop
//your code, a card is near to the antenna, try to read it.
readVal = Serial.read();
if (readVal == 2) {
counter = 0; // start reading
} else if (readVal == 3) {
processTag();
clearSerial();
counter = -1;
} else if (counter >= 0) {
readData[counter] = readVal;
++counter;
}
}
reset the card status when no RFID signal comes in && card status is true,
if ( (!(Serial.available() > 0)) && (card_status == 1) ) {
card_status = 0; //enable to read card again
//no signal, no card is near to the antenna.
}
You can set a delay (e.g. delay(2000)) after reading the (end of tag). A delay of (say) 2 seconds will allow the user to move the card far enough away from the reader. Note that delay is a blocking command which might not suit your purposes, in which case you could be looking at using the millis count to activate/deactivate the Serial.read.
Another option is to accept the multiple reads, but keep a state of which card has been read. If the new card number is the same as the old card number (within a reasonable timeframe) then just ignore.
Please, help me. I'm trying to connect the 74HC165 (8-bit input shift register) to Arduino UNO via SPI to check the state of 8 buttons. The response is going to be processe to change variable "controls", but it doesn't work properly.
Here is the code:
#include <SPI.h>
/* Latch contact */
enum { REG_LATCH = 8 };
int speed = 100;
/* Variable to store the Controls state for further transfer */
static uint8_t controls = 0;
void setup()
{
/* Turn ON the UART */
Serial.begin(9600);
/* Turn On the SPI */
SPI.begin();
pinMode(REG_LATCH, OUTPUT);
digitalWrite(REG_LATCH, HIGH);
}
void loop()
{
/* Storing the previous system state */
static uint8_t previous_input = 00000000;
digitalWrite(REG_LATCH, LOW);
digitalWrite(REG_LATCH, HIGH);
/* Read the inputs from shift register */
uint8_t input = SPI.transfer(0);
/* If anything has ben changed - report to UART */
if (input != previous_input)
{
/* Remebmer changed positions */
uint8_t changed = input ^ previous_input;
/* Remember current state */
previous_input = input;
Serial.println("Buttons State:\t\tControls State:");
/* Run trough all inputs from shift register */
for (int i = 0; i < 8; i++)
{
/* Print the state of currently checked input*/
Serial.print(input & 1);
/* If button is pressed and previously it was not, then */
if ((input & 1) & (changed & 1))
{
/* Highlight the current changes in system */
Serial.print("_");
/* Toggle controls in this position */
controls = controls ^ (1 << i);
}; /*Otherwise do nothing*/
/* Move to next bit of inputs. */
input >>= 1;
changed >>= 1;
};
Serial.print("\t\t");
for (int i = 0; i < 8; i++)
{
/* Print current control */
Serial.print(controls);
controls >>= 1;
}
Serial.println();
}
}
And what it writes to the Serial:
1) After pressing button 1:
Buttons State: Controls State:
1_0000000 10000000
2) When it releases:
Buttons State: Controls State:
00000000 00000000
3) After pressing button 7:
Buttons State: Controls State:
0000001_0 64321684210
4) After its releasing:
Buttons State: Controls State:
00000000 00000000
5) After pressing button 1:
Buttons State: Controls State:
1_0000000 10000000
6) When it releases:
Buttons State: Controls State:
00000000 00000000
How it supposed to work:
1) After pressing button 1:
Buttons State: Controls State:
1_0000000 10000000
2) After its release:
Buttons State: Controls State:
00000000 10000000
3) After pressing button 7:
Buttons State: Controls State:
0000001_0 10000010
4) After its releasing
Buttons State: Controls State:
00000000 10000010
5) After next pressing of button 1:
Buttons State: Controls State:
1_0000000 00000010
6) After its releasing:
Buttons State: Controls State:
00000000 00000010
Help me, please.
What am I doing wrong?
First check your shift register is connected correctly. The best way of distinguishing hardware issues with software issues is to plug an oscilloscope on the output pin of your shift register.
Your REG_LATCH pin must be plugged to pin1 of your shift register (assuming we are talking about this one http://www.nxp.com/documents/data_sheet/74HC_HCT165.pdf).
The way it works is that you must pull this pin down, transfer data then pull it up. Thus the sequence is rather:
digitalWrite(REG_LATCH, LOW);
/* Read the inputs from shift register */
uint8_t input = SPI.transfer(0);
digitalWrite(REG_LATCH, HIGH);
Then instead of shifting index and changed in your loop, I would have used this:
input & i
changed & i
or
input & (7 - i)
changed & (7 - i)
depending on the order your want to handle your bits.
I've figured out the problem.
I've made a mistake in depicturing of "Controls" state. Togling was working as it was supposed to work.
This is code for proper presenting:
#include <SPI.h>
/* ----------------------------------------------------------------------- */
/* Global System variables */
/* ----------------------------------------------------------------------- */
/* Storing the previous system state */
static uint8_t previous_input = 0;
/* Variable to store the Controls state for further transfer */
static uint8_t controls = 0;
/* ----------------------------------------------------------------------- */
/* Configuration of shift input register 74HC165 */
/* Latch contact */
enum { REG_LATCH = 8 };
/* ----------------------------------------------------------------------- */
void setup()
{
/* Turn ON the UART */
Serial.begin(9600);
/* Turn On the SPI */
SPI.begin();
pinMode(REG_LATCH, OUTPUT);
digitalWrite(REG_LATCH, HIGH);
}
/* ----------------------------------------------------------------------- */
void print_bin_to_serial(int digit){
/* Run trough all inputs from shift register */
for (int i = 0; i < 8; i++)
{
/* Print the state of currently checked input*/
Serial.print(((digit << i) >> 7) & 1);
};
}
/* ----------------------------------------------------------------------- */
void loop()
{
digitalWrite(REG_LATCH, LOW);
digitalWrite(REG_LATCH, HIGH);
/* Read the inputs from shift register */
uint8_t input = SPI.transfer(0);
/* If anything has ben changed - report to UART */
if (input != previous_input)
{
/* Remember changed positions */
uint8_t changed = input ^ previous_input;
/* Remember current state */
previous_input = input;
/* Fixing, what positions had to be switched */
uint8_t items_to_change = (input & changed);
controls ^= items_to_change;
/* Code is just for printing */
Serial.println("Buttons State:\t\tChanged:\t\tItems to change:\tControls State:");
print_bin_to_serial(input);
Serial.print("\t\t");
print_bin_to_serial(changed);
Serial.print("\t\t");
print_bin_to_serial(items_to_change);
Serial.print("\t\t");
print_bin_to_serial(controls);
Serial.println();
};
}
#Tom, thanks for advise. That didn't fix a problem, but helped to make a code shorter.
I am trying to wait for user input to start a program operation and then when the user sends a stop command, the loop stops running. I have been unable to get the Serial port to keep reading an input while the loop is running.
So I want the user to Press 1 and then it'll go into the loop and will display the data from the interrupt. But I want it to keep monitoring the Serial Input so when I type in 2, I will get out of the loop and stop printing to the Serial Port.
The serial port isn't registering my second input.
I left out some of the code, but the important stuff should be there.
int userStart = 0; // Holder for user input to start program
int userStop = 0; // Holder for user input to stop program
void setup() {
Serial.begin(115200);
pinMode(motorEncoderA, INPUT);
digitalWrite(motorEncoderA, HIGH); // Pull up resistor
pinMode(motorEncoderB, INPUT);
digitalWrite(motorEncoderB,HIGH); // Pull up resistor
// Interrupt on change of Pin A
attachInterrupt(digitalPinToInterrupt(2), encoderFunc, CHANGE);
Serial.print("Press 1 to start the Process & 2 to Stop");
}
void loop() {
if (Serial.available() > 0)
{
userStart = Serial.read();
if (userStart = 1) {
Serial.print('\n');
while(userStop != 2) {
unsigned long timee = millis();
// Only update if the shaft has moved
if (encoderPositionLast != rotationCounter) {
Serial.print("Time: ");
Serial.print(timee);
Serial.print(" Count: ");
Serial.print (rotationCounter);
Serial.print('\n');
encoderPositionLast = rotationCounter;
Serial.print(userStart);
}
if (Serial.available() > 0) {
userStop = Serial.read();
Serial.print(userStop);
}
}
}
}
Well, I think your problem is that userStart and userStop should not be 1 and 2, but '1' and '2'.
That said, there are some things in your code I dislike.
First of all why is everybody using int as the base type for all numeric variables? If one single byte is enough, use it. On 32bit machines int and byte are almost the same, but on 8bit ones working with ints wastes space and time.
Secondly, I highly discourage you to block the loop function, otherwise you won-t be able to do anything else. Instead, use a variable to track wheter you are running or not, update it with the serial interface, and then execute the code if you are running.
This code should do it. And IMHO it is much better than blocking the loop:
bool running = false;
void setup()
{
...
running = false;
}
void loop()
{
if (Serial.available() > 0)
{
switch(Serial.read())
{
case '1':
running = true;
Serial.print('\n');
break;
case '2':
running = false;
Serial.print("stopped");
break;
}
}
if (running)
{
unsigned long timee = millis();
// Only update if the shaft has moved
if (encoderPositionLast != rotationCounter) {
Serial.print("Time: ");
Serial.print(timee);
Serial.print(" Count: ");
Serial.print (rotationCounter);
Serial.print('\n');
encoderPositionLast = rotationCounter;
Serial.print("running");
}
}
}