Card Details on OLED Display using RFID - Arduino Uno - arduino

I'm still learning the ropes so forgive me if the answer to this is obvious. I'm using the Arduino Uno and a RC522 RFID card reader. My aim is to scan a card on the reader and have the I2C OLED display show me the name of the person who has scanned their card. This is the code for the program I'm using -
#include <U8glib.h>
#include <LiquidCrystal.h>
#include <RFID.h>
#include <SPI.h>
#define SS_PIN 10
#define RST_PIN 9
RFID rfid(SS_PIN, RST_PIN);
int serNum[5];
String cardno;
int interval = 15000; // millisec
long now = 0;
long lasttime = millis();
// change Reader ID to your name
String readerID = "CCE3050";
void setup() {
Serial.begin(9600);
SPI.begin();
rfid.init();
}
void loop() {
now = millis();
if (now > lasttime + interval) {
lasttime = now;
Serial.print(readerID);
Serial.print(":");
Serial.println("I am alive");
}
if (rfid.isCard()) {
if (rfid.readCardSerial()) {
lasttime = now;
cardno = String(rfid.serNum[0]) +
String(rfid.serNum[1]) +
String(rfid.serNum[2]) +
String(rfid.serNum[3]) +
String(rfid.serNum[4]);
Serial.print(readerID);
Serial.print(":");
Serial.println(cardno);
}
}
delay(5000);
}
So far, each time a card is tagged, the card number is displayed on the serial monitor. However, I would like to assign a name to the card and display that name on the OLED whenever the card is tagged onto the reader. Is there a way to do this?

I suggest creating a struct to hold an id and its associated name.
typedef struct {
String id;
String name;
} User;
Create an array to hold multiple instances of the struct.
User users[MAX_USER_NUM]; // define the size
User user1 = {"123", "A"}; // {"id", "name"}
users[0] = user1;
User user2 = {"234", "B"};
users[1] = user2;
User user3 = {"345", "C"};
users[2] = user3;
You can then retrieve a user name by passing an id to a function like this.
String lookup(String id) {
for (int i = 0; i < MAX_USER_NUM; i++) {
if (users[i].id == id) {
return users[i].name;
}
}
return "";
}

An easy way to do it would be store a json with in SPIFF.
The structure of the JSON could be like:-
{[{"card_no: 123, "name": "Jhon"},{ "card_no": 124, "name": "Sam"}]}
The advantage of using SPIFF is that you can retrieve the data even after you reboot.
After you get the card number you can find the card number in the Json data and show the name

Related

BLE scan only gets the name of some devices on the first scan

I have the following code:
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEAdvertisedDevice.h>
static void log(String message) {
Serial.println(message);
}
const char* deviceName = "BLEScanner";
BLEScan* pBLEScan;
void setup() {
Serial.begin(115200);
log("Setup!");
BLEDevice::init(deviceName);
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
log("Listing BLE Sensors");
BLEScanResults foundSensors = pBLEScan->start(30, false);
int count = foundSensors.getCount();
for (int i = 0; i < count; i++) {
BLEAdvertisedDevice bleSensor = foundSensors.getDevice(i);
String sensorName = bleSensor.getName().c_str();
String address = bleSensor.getAddress().toString().c_str();
log(address + " " + sensorName);
}
log("Sleeping");
sleep(10);
}
And when running it I get the following output:
Setup!
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89 LM0845
c4:7c:8d:6a:36:cf Flower care
c4:7c:8d:6a:45:6b Flower care
c4:7c:8d:6a:46:2c Flower care
de:d5:2a:8e:1e:fd Tile
Sleeping
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89
dc4:7c:8d:6a:36:cf
dc4:7c:8d:6a:45:6b
dc4:7c:8d:6a:46:2c
de:d5:2a:8e:1e:fd Tile
Sleeping
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89
c4:7c:8d:6a:36:cf
dc4:7c:8d:6a:45:6b
dc4:7c:8d:6a:46:2c
de:d5:2a:8e:1e:fd Tile
... and so on
For some reason I only get the names of some of the devices the first time, is this a known error and what can be done about it?
I have tried to put a pBLEScan->clearResults(); before I start a scan but that did not help.
I'm using an ESP32 Adafruit feather.
The only solution I have found is to put the BLEDevice::init(deviceName); inside the loop and then run BLEDevice::deinit(); before sleep!

Need some help in understanding some codes

I'm using RFID RC522 module in Arduino what the code does is, whenever the RFID tag is close to the reader it will read the tag no, with the current timestamp. But i need help in understanding the code line by line. I've understood a few lines which commented in the code but the rest i need help. Thank you
#include <RFID.h>
#include <SPI.h>
#define SS_PIN 10
#define RST_PIN 9
RFID rfid(SS_PIN, RST_PIN);
int serNum[4];
String cardno;
int interval = 15000; // millisec
long now = 0;
long lasttime = millis(); //millis() no.of millisec the sketch was runnning
String readerID = "100"; // This is the reader ID
void setup() {
Serial.begin(9600); //setting data rate in bits per second 9600
SPI.begin();
rfid.init();
}
void loop() {
now = millis();
if (rfid.isCard()) {
if (rfid.readCardSerial()) {
lasttime = now;
cardno = String(rfid.serNum[0]) +
String(rfid.serNum[1]) +
String(rfid.serNum[2]) +
String(rfid.serNum[3]) +
String(rfid.serNum[4]);
Serial.print(readerID);
Serial.print(":");
Serial.println(cardno); //printing the cardno in the serial monitor
}
}
rfid.halt();
delay(1000);
}
There are unused variables in your code. Let's get rid of them so that it is less confusing. I also added comments that explain the if statements.
#include <RFID.h>
#include <SPI.h>
#define SS_PIN 10
#define RST_PIN 9
RFID rfid(SS_PIN, RST_PIN);
String cardno;
String readerID = "100";
void setup() {
Serial.begin(9600);
SPI.begin();
rfid.init();
}
void loop() {
if (rfid.isCard()) { // Look for a card. If found, return true.
if (rfid.readCardSerial()) { // Read the serial number of the card. if successful, return true.
cardno = String(rfid.serNum[0]) +
String(rfid.serNum[1]) +
String(rfid.serNum[2]) +
String(rfid.serNum[3]) +
String(rfid.serNum[4]);
Serial.print(readerID);
Serial.print(":");
Serial.println(cardno);
}
}
rfid.halt();
delay(1000);
}
Guessing from your comment, I think you want to understand how RFID class is implemented. I suggest looking at RFID.h and RFID.cpp.
RFID class has an array called serNum. My guess is that when you call readCardSerial(), an instance of RFID tries to store a card number in this array. If the operation is successful, it returns true.

Get Arduino Serial data from RF remote with RF receiver having TX

I have this 433 Mhz remote with 12 key using PT2264 and having universal receiver module to decode signal from this remote. Receiver module output in TX pin with 9600 baud rate.
It send data after receiving from remote as REMOTE_ID:KEY_NUMBER.
for example after pressing key 1 from remote I get #AAAA:01 this as data.
Problem is that it does not send any data if pressed once. Instead we have to keep remote key pressed to transmit key code. This creates a burst of continuous data for that key in format #AAAA:01.
Now my problem is I want to interface this remote to ESP8266 and toggle a http resource. I understand this very typical setup, but i need it this way. My problem is how to detect multiple same key as one event on serial so that if it happens again I can achieve the toggle action.
So in short i want to toggle a resource upon pressing switch on remote.
Hardware setup is simple:
Ive attached 433Mhx receiver modules TX pin to ESP8266's D13 and using SoftwareSerial to read data.
Currently I get :
#AAAA:01#AAAA:01#AAAA:01#AAAA:01#AAAA:01#AAAA:01#AAAA:01#AAAA:01#AAAA:01#AAAA:01
I want it only to detect as one #AAAA:01
but if pressed again after few seconds its second #AAAA:01 with which we can toggle some variable.
code is simple.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(12, 14, false, 256);//RX, TX
String readString; //main captured String
int buttonState = LOW; //this variable tracks the state of the button, low if not pressed, high if pressed
int ledState = 0; //this variable tracks the state of the LED, negative if off, positive if on
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 10; // the debounce time; increase if the output flickers
const byte interruptPin = 13;
void setup() {
pinMode(interruptPin, INPUT_PULLUP);
Serial.begin(9600);
mySerial.begin(9600);
}
void loop() {
if (mySerial.available()) {
char c = mySerial.read(); //gets one byte from serial buffer
if (c == '#') {
//do stuff
int ind1 = readString.indexOf(':');
String id = readString.substring(0, ind1);
String key = readString.substring(ind1 + 1);
Serial.println(id);
if (id == "AAAA") {
Serial.println(millis());
if ((millis() - lastDebounceTime) > 50 ) {
//lastDebounceTime = millis();
Serial.println("key Pressed: ");
Serial.println(key);
}
}
readString = ""; //clears variable for new input
id = "";
key = "";
}
else {
readString += c; //makes the string readString
}
}
}
I tried debauching like code with millis() but it did not work.

Global variable arduino

I'm using I2C to communicate a Master Arduino to 4 Slaves Arduinos, and an Shield (OULIMEX Shield LCD 16x2) on every Arduino slave.
I send Data from the master to slaves using I2C. So I use this code in the master :
#include <Wire.h>
#include <math.h>
#include <floatToString.h>
double incomingData;
void setup()
{
Wire.begin();
Serial.begin(9600);
incomingData = Serial.parseFloat(); //read incoming data
}
void loop()
{
delay (1000);
if (Serial.available())
{
incomingData = Serial.parseFloat(); //read incoming data
Wire.beginTransmission(8); // transmit to device #8
if ((M==0) || (M==1) || (M==2))
Wire.beginTransmission(8); // transmit to device #8 *****************************************************************
else
Wire.beginTransmission(7); // transmit to device #7 *****************************************************************
M++;
if (M==5)
M=0;
String a = "";
a = floatToString(test,incomingData,3,5,true);
for(i=0; a[i]!='\0'; ++i); // length of the string
Wire.write(i);
Wire.write(floatToString(test,incomingData,3,5,true)); // sends one byte
Wire.endTransmission(); // stop transmitting
}
}
I wanted the Data to be printed on the Shield, but I'm connecting all slaves with the same way with the master. For that I have two problems :
1- The global data I'm using to print value is always printed as 0, and not giving the real value;
2- All Shields print the same thing : For exemple, I print "hello" in the first Shield, and I print "hi" in the second Shield, but bouth are printing the same thing (hello or hi).
The code using for the first slave is :
#include <LCD16x2.h>
#include <Wire.h>
LCD16x2 lcd;
int buttons;
int sensorPin = A0; // select the input pin for the potentiometer
int sensorValue = 0; // variable to store the value coming from the sensor
float numOut;
int comp=1 ;
String wordd = "";
int M =0;
void setup()
{
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}
void loop()
{
delay(500);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
wordd = "";
int x = Wire.read();
for (int i=0; i<=x; i++)
{
char c = Wire.read();
wordd += c;
}
numOut = wordd.toFloat();
Serial.println(numOut,3); // print the integer
}
Thank you in advance !!
I think it's due to a poor program structure in master shield.
This block selects the slave but on the first line you already select #8
I think this is confusing for the slaves.
Wire.beginTransmission(8); // transmit to device #8
if ((M==0) || (M==1) || (M==2))
Wire.beginTransmission(8); // transmit to device #8
else
Wire.beginTransmission(7); // transmit to device #7
This block should be at the end of the function
M++;
if (M==5)
M=0;
Then you parse the value in a string.
But leave out the first char because you write ++i instead of i++
Moreover you close the loop with ; so it does nothing
String a = "";
a = floatToString(test,incomingData,3,5,true);
for(i=0; a[i]!='\0'; ++i); // length of the string
Finally you write the ordinal number of the byte
And then again the Whole string
So you should get "0" (or "1" because of ++i)
followed by your number if Wire.write() supports it
Wire.write(i);
Wire.write(floatToString(test,incomingData,3,5,true)); // sends one byte
Wire.endTransmission(); // stop transmitting
}
Your sketch should be:
if (Serial.available())
{
incomingData = Serial.parseFloat(); //read incoming data
String a = "";
a = floatToString(test,incomingData,3,5,true);
if ((M==0) || (M==1) || (M==2))
Wire.beginTransmission(8); // transmit to device #8
else
Wire.beginTransmission(7); // transmit to device #7
for(i=0; a[i]!='\0'; ++i) // length of the string
Wire.write(a[i]); // write one byte
Wire.endTransmission(); // stop transmitting
M++;
if (M==5) M=0;
}
Let me know if this works.
I already ask this question but I think I have the answer of it. A global variable have to be diclared befor the void setup, and the void loop too, like that :
type YourGlobalVariable;
void setup()
{
}
void loop()
{
}
So, it is exactly how I did already. The reason it didn't work for me, it was cause of I used this function :
void receiveEvent(int howMany) {}
I don't really know what are the properties of it that let it not work for a global variables, but It works like I sayd already.
Thank you all

How can I read date and time data from RTC of sim900 module using arduino?

#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
SMSGSM sms;
boolean started=false;
int count = 0;
void setup()
{
pinMode(5, INPUT); // input pin for switch
Serial.begin(9600);
if (gsm.begin(2400))
{
Serial.println("\nstatus=READY");
started=true;
}
else Serial.println("\nstatus=IDLE");
delay(1000);
}
void loop()
{
if (digitalRead(5)==1)
{
delay(500);
if (digitalRead(5)==1)
{
count = count+1;
/*if(started)
{
if (sms.SendSMS("+12345678", "ALARM"))
Serial.println("\nSMS sent OK");
}*/
Serial.println("Count = ");
Serial.println(count);
readtime();
Serial.println(content);
}
}
else
{
Serial.println("Normal");
}
}
I use sim 900 with arduino to detect change of input pin 5 and then ALARM to user. I have a few question that need your help
How can I know which pin that sim 900 use to communicated for sent sms? I use jumper at D2 and D3. Did it use these two pins? because in my program I use an .h include file which I didn't know detail inside it.
How can I read date and time data from RTC in sim 900 module and store in a variable and use them for data logger later? I know that if I have already set date and time in RTC, it can be read by "AT+CCLK?" and it return date and time data. But how can I use this command in my program?
I found this code and work for me. First you ask for time and then expect answers and parse it.
const char* const SIM900::getTimeStamp(){
Serial2.print("AT+CCLK?"); //SIM900 AT command to get time stamp
Serial2.print(13,BYTE);
delay(2000);
if (Serial2.available()>0){
int i = 0;
while (Serial2.available()>0){
timeStamp[i]=(Serial2.read());
i++;
}
}
int years = (((timeStamp[25])-48)*10)+((timeStamp[26])-48);
int months = (((timeStamp[22])-48)*10)+((timeStamp[23])-48);
int days = (((timeStamp[19])-48)*10)+((timeStamp[20])-48);
int hours = (((timeStamp[28])-48)*10)+((timeStamp[29])-48);
int mins = (((timeStamp[31])-48)*10)+((timeStamp[32])-48);
int secs = (((timeStamp[34])-48)*10)+((timeStamp[35])-48);
//YOUR CODE HERE
}

Resources