I am trying to complete an arduino project which uses RFID cards to prompt a DFPlayer mini to play tracks. (The original project is called Juuke).
I have near-on everything working but am having a problem calling the DFPlayer to play from specific folders. It seems the playFolder instruction does not work at all (neither does the playLargeFolder or the playMP3folder). Currently the only instructions I seem to be able to get it to respond to are myDFPlayer.play and myDFPlayer.loopFolder
The project is supposed to work as follows:
each RFID card is programmed with a number,
when you scan and RFID card, it reads the number
it plays the mp3 track from the SDcard with that number (4-digit file name prefixed with zeros)
As far as I can tell the myDFPlayer.play instruction is working, but that seems to play the file based on what order it was added to the SD card, rather than by reading the file name?
The actual situation I am trying account for is that some of the mp3 files are 'singles' so it only needs to play one track. This works fine with the myDFPlayer.play instruction (as long as they were added to the SDcard in the order expected by the filename).
However, other mp3 files are 'albums' so when I scan the RFID I'd like it to open a folder with a group of mp3 files, and loop through all the files in that folder once before stopping.
My plan is to have all the 'singles' in folder with the name 80, if the RFID card number is above 80, the DFPlayer will open folder 80 and play the file with the corresponding filename to the number of the RFID card e.g. if I present RFID card '93', the DFPlayer will open folder 80 and play file 0093.mp3
All the folders below 80 will be 'album folders'. So if I present an RFID card with number below 80 , the DFPlayer will open the folder with the corresponding file name and play track 1 before looping through each file in that folder once, then stopping. e.g. if I present RFID card '42', the DFPlayer will open Folder 42 and play track 1.
Currently, I cannot get the DFPlayer to respond to the instruction myDFPlayer.playFolder in any format. Neither does it respond to myDFPlayer.playMP3Folder or myDFPlayer.playLargeFolder.
Things I have considered and accounted for...
I am adding the mp3 files from my Mac, I am using dot_clean to clean the SD card before putting it into the DFPlayer.
I have tried every variation of folder and file names (4-digit zero prefixed e.g. 0034; 3-digit zero prefixed e.g. 034; folders with 2digit zero prefixed e.g. 07) Nothing seems to work.
Rather than use the number from the RFID card I have just hard coded it to play a specific folder whatever card is there (i.e. myDFPlayer.playFolder(2,1) and the DFPlayer does not respond.
Moving to a Windows machine, formatting the SD card (exFAT is the only format option I get?) an re-adding the mp3 files.
putting the mp3 files in a root file labelled 'mp3'.
having only files on the SD card that are labelled 01 , 02 , 03 etc
The serial monitor shows that the code is working fine except for the bit where the DFPlayer is supposed to find the folder and play the file. There is a small LED on the DF Player that seems to indicate when it is playing a file, that LED does not turn on at all when the playFolder instruction is being given.
This is the code... I have tried a lot of variations in the //PLAY SONG section.
/*
Thanks to Original Author: ryand1011 (https://github.com/ryand1011)
Edited by Ananords -
See: https://github.com/miguelbalboa/rfid/tree/master/examples/rfid_write_personal_data
Uses MIFARE RFID card using RFID-RC522 reader
Uses MFRC522 - Library
-----------------------------------------------------------------------------------------
MFRC522 Arduino Arduino Arduino Arduino Arduino
Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
Signal Pin Pin Pin Pin Pin Pin
-----------------------------------------------------------------------------------------
RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
SPI SS SDA(SS) 10 53 D10 10 10
SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
PS: IF THE PLAYER FAILS TO START WHEN THE SERIAL MONITOR IS NOT OPEN, TRY TO COMMENT OUT Serial.begin(115200);
*/
#include <SPI.h>
#include <MFRC522.h>
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
const int playPauseButton = 4;
const int shuffleButton = 3;
const byte volumePot = A0;
int prevVolume;
byte volumeLevel = 0; //variable for holding volume level
boolean isPlaying = false;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
SoftwareSerial mySoftwareSerial(5, 6); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
//*****************************************************************************************//
void setup() {
Serial.begin(115200); // Initialize serial communications with the PC, COMMENT OUT IF IT FAILS TO PLAY WHEN DISCONNECTED FROM PC
mySoftwareSerial.begin(9600);
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
pinMode(playPauseButton, INPUT_PULLUP);
pinMode(shuffleButton, INPUT_PULLUP);
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
}
Serial.println(F("DFPlayer Mini online. Place card on reader to play a specific song"));
//myDFPlayer.volume(15); //Set volume value. From 0 to 30
volumeLevel = map(analogRead(volumePot), 0, 1023, 0, 30); //scale the pot value and volume level
myDFPlayer.volume(volumeLevel);
prevVolume = volumeLevel;
//----Set different EQ----
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
// myDFPlayer.EQ(DFPLAYER_EQ_POP);
// myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
// myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
// myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
// myDFPlayer.EQ(DFPLAYER_EQ_BASS);
}
//*****************************************************************************************//
void loop() {
volumeLevel = map(analogRead(volumePot), 0, 1023, 0, 30); //scale the pot value and volume level
if (prevVolume != volumeLevel){
myDFPlayer.volume(volumeLevel);
}
prevVolume = volumeLevel;
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
//some variables we need
byte block;
byte len;
MFRC522::StatusCode status;
if (digitalRead(playPauseButton) == LOW) {
if (isPlaying) {
myDFPlayer.pause();
isPlaying = false;
Serial.println("Paused..");
}
else {
isPlaying = true;
myDFPlayer.start();
Serial.println("Playing..");
}
delay(500);
}
if (digitalRead(shuffleButton) == LOW) {
myDFPlayer.next();
Serial.println("next Play");
isPlaying = true;
delay(1000);
}
//-------------------------------------------
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( mfrc522.PICC_IsNewCardPresent()) {
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
Serial.println(F("**Card Detected:**"));
//-------------------------------------------
mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); //uncomment this to see all blocks in hex
//-------------------------------------------
Serial.print(F("Number: "));
//---------------------------------------- GET NUMBER AND PLAY THE SONG
byte buffer2[18];
block = 1;
len = 18;
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block, buffer2, &len);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
//PRINT NUMBER
String number = "";
for (uint8_t i = 0; i < 16; i++)
{
number += (char)buffer2[i];
}
number.trim();
Serial.print(number);
//PLAY SONG
if (number.toInt()>79){
myDFPlayer.playFolder(80, number.toInt());
isPlaying = true;
delay(1000);
}
else {
myDFPlayer.playFolder(number.toInt(), 1);
isPlaying = true;
delay(1000);
}
//----------------------------------------
Serial.println(F("\n**End Reading**\n"));
delay(1000); //change value if you want to read cards faster
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}
//*****************************************************************************************//
I have mentioned above a range of things I have tried, nothing seems to work. I am a beginner so I am not sure what there is left that could be the problem!
Related
I am a novice to Arduino. I came across an article on rs 485 and currently trying to implement the same between 2 arduino unos. I copied code from internet which is pretty simple but I am unable to make communication work properly. Here is the code for master arduino with explanation of what I am trying to do.
**Master Arduino Code**
/* master will send a message I1LF where I shows start of master message by master.
* 1 shows the slave device No. from whom data is to be fetched and L
* shows that master wants to read slave's sensor data
* and F indicates finish of message by master.
* slave will respond by sending Serial.println(i1) where i is slave no and 1 is to let master know that
* correct slave is sending data. then slave would send sensor_value and then f indicates end of slave message.
* master will display data read from rs 485 bus.
*/
#include<LiquidCrystal.h> //Library for LCD display
//function
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int Enable = 2;
int value1=0;
void setup()
{
Serial.begin(9600);
pinMode(Enable, OUTPUT);
digitalWrite(Enable, HIGH); // put master arduino into transmission mode.
lcd.begin(16,2);
lcd.clear();
}
void loop()
{
Serial.print('I'); // I indicates master has started communication.
Serial.print('1'); // this is the address of slave from whom data is to be fetched.
Serial.print('L'); // this means master wants to read sensor data.
Serial.print('F'); // this means end of message.
Serial.flush(); // wiat untill all data has been pushed to the serial.
digitalWrite(Enable, LOW); // put master into receiving mode.
if(Serial.find('i')) // i will be sent (to indicate start of slave
//message , by the slave that was prompted by
//master.
{
int slave = Serial.parseInt(); // check which slave is sending
//data.
value1 = Serial.parseInt();
if(Serial.read() == 'f' && slave == 1) // f indicates end of message
//sent by slave and 1 is the
//address of the slave sent by
// the slave so that master can
//recognize which slave is this.
{
lcd.setCursor(0,0);
lcd.print("Slave : ");
lcd.setCursor(11,0);
lcd.print(value1);
}
}
digitalWrite(Enable, HIGH);
delay(300);
}
This is the slave arduino code
#include<LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
const int Enable = 2;
const int SlaveNumber = 1;
void setup()
{
Serial.begin(9600);
pinMode(Enable, OUTPUT);
digitalWrite(Enable, LOW); // initially put slave in receiving mode
pinMode(A0, INPUT);
lcd.begin(16,2);
lcd.clear();
}
void loop()
{
if(Serial.available())
{
if(Serial.read()=='I') // all slaves will detect I on rs 485 bus which //means master has started commmunication.
{
int Slave = Serial.parseInt(); // read next character on rs 485 bus
//which would definitely be a digit
//indicating slave no to whom master
//wishes to communicate.
if(Slave == SlaveNumber) // check if master wants to commnucate
//with you.
{
char command = Serial.read(); // read next character in
//serial buffer which would be
//command L
delay(100);
if(command == 'L')
{
if(Serial.read()=='F') // if master's message has
//finished.
{
int AnalogValue = analogRead(0); // read sensor
digitalWrite(Enable, HIGH); // put slave in
//transmission mode.
Serial.print("i"); // i indicates start of
//slave message
Serial.println(SlaveNumber); // send slave no so that
//master can identify which
//slave he is receiving
//data from.
Serial.print(AnalogValue);
Serial.print("f"); // indicates end of message by the
//slave.
Serial.flush();
digitalWrite(Enable, LOW); // put slave in
//listening ( receivig ) mode
}
}
}
}
}
}
This is screen shot of proteous simulation showing Master unable to read slave1's sensor data
enter image description here
I assessed that problem arose because of master and slave both being in transmission mode so I attached a not gate between master's enable pin and slave's enable pin and then master is working fine. but practically attaching a not gate wont be possible. that's why I want to know how to ensure that enable of both master and slave is not high simultaneously. I have tried a couple of strategies and introduced delays at different locations in the code but nothing seems to work. by hit and trial it starts to work sometimes but I want to know the correct way of doing so.
This is screen shot of proteous simulation which shows master reading correctly slave1 data only after I attach a not gate between master Enable pin and Slave's Enable pin.
Code for both master and slave and circuit is exactly the same as before. only a not gate has been used between master's enable pin and slave's enable pin.
enter image description here
I tried another library madleech/Auto485 but that i also showing the same problem. have tried a couple of times adding delays at different locations in master code but to no use. i know problem is because of enable pins of both MAX 485 modules connected to 2 arduinos going high simultaneously but i am unable to figure out how to address this issue.
You need to wait for each byte to be available before reading the serial port.
In your code:
if(Serial.available()) // you wait
{
if(Serial.read()=='I') // all slaves will detect I on rs 485 bus which //means master has started commmunication.
{
// parseInt() does wait for a byte to be availeble, so that works...
int Slave = Serial.parseInt();bus
if(Slave == SlaveNumber)
{
// Here serial.read() will most likely return -1, since it is very
// unlikely that a byte is already available at this point.
char command = Serial.read();
// ...
You should wait for the serial port to have received bytes before reading them.
You can try inserting a loop before calling read(), as in:
while (!Serial.available()) {} // wait for something to read
char byteRead = Serial.read();
This blocking code should help fix the code as you have it now. You should probably explore non-blocking ways of reading serial commands, such as using some sort of finite state machine algorithm. As a rule of thumb, embedded software should avoid blocking.
A bit of context, I am participating in the UK CanSat competition. I am sorting out the communication between the CanSat and the ground station. We are using LoRa transceivers as required per the competition. We are using a raspberry pi pico as a emitter and an Arduino nano in the ground station as a receiver.
The LoRa module we are using is this one.
Long story short, when I receive the message in the ground station, there are multiple symbols, here is a picture:
Here is the code for the Arduino (receiver):
// Arduino9x_RX
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messaging client (receiver)
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example Arduino9x_TX
#include <SPI.h>
#include <RH_RF95.h>
#define RFM95_CS 10
#define RFM95_RST 9
#define RFM95_INT 2
// Change to .0 or other frequency, must match RX's freq!
#define RF95_FREQ 433.0
// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
// Blinky on receipt
#define LED 13
void setup() {
pinMode(LED, OUTPUT);
pinMode(RFM95_RST, OUTPUT);
digitalWrite(RFM95_RST, HIGH);
while (!Serial);
Serial.begin(9600);
delay(100);
Serial.println("Arduino LoRa RX Test!");
// manual reset
digitalWrite(RFM95_RST, LOW);
delay(10);
digitalWrite(RFM95_RST, HIGH);
delay(10);
while (!rf95.init()) {
Serial.println("LoRa radio init failed");
while (1);
}
Serial.println("LoRa radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
if (!rf95.setFrequency(RF95_FREQ)) {
Serial.println("setFrequency failed");
while (1);
}
Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
// Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
// The default transmitter power is 13dBm, using PA_BOOST.
// If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
// you can set transmitter powers from 5 to 23 dBm:
rf95.setTxPower(23, false);
}
void loop() {
if (rf95.available()) {
// Should be a message for us now
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
//char buf = (char*)buf;
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len)) {
digitalWrite(LED, HIGH);
Serial.print("Got: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC);
} else {
return;
}
}
}
Disclaimer this code was extracted from the internet.
And here is the code for the Raspberry pi pico (emitter):
import board
import busio
import time
import digitalio
import adafruit_rfm9x
import adafruit_bmp280
"Led configuration"
# Led amarillo
ledambar = digitalio.DigitalInOut(board.GP16)
ledambar.direction = digitalio.Direction.OUTPUT
# Led azul
ledazul = digitalio.DigitalInOut(board.GP17)
ledazul.direction = digitalio.Direction.OUTPUT
"LoRa"
# LoRa radio setup
spi = busio.SPI(clock=board.GP2, MOSI=board.GP3, MISO=board.GP4)
cs = digitalio.DigitalInOut(board.GP6)
reset = digitalio.DigitalInOut(board.GP7)
rfm9x = adafruit_rfm9x.RFM9x(spi, cs, reset, 433.0)
print("RFM9x radio ready")
"Not LoRa from here"
"BMP280 Sensor"
# BMP280 comunication start up
i2c = busio.I2C(scl=board.GP15, sda=board.GP14)
bmp280_sensor = adafruit_bmp280.Adafruit_BMP280_I2C(i2c, address=0x76)
# BMP280 sensor readings
def read_temperature():
return bmp280_sensor.temperature
def read_pressure():
return bmp280_sensor.pressure
while True:
ledazul.value = True
"LoRa"
rfm9x.send("Hello World, this is a test, why does this not work? im going mad!!!!")
print("Radio mensage sent")
"Not LoRa from here"
ledazul.value = False
cansat_temperature = read_temperature()
print("TEMPERATURE:")
print(cansat_temperature)
cansat_pressure = read_pressure()
print("PRESSURE:")
print(cansat_pressure)
print(" ")
time.sleep(2.5)
Disclaimer, this code is designed to do more things than just LoRa communication. The LoRa part of the code is below the tag: "LoRa".
If you have any recommendations on how to improve my code in any way, just let me know, it would be really helpful.
Thank you.
I have tried soldering the antennas, changing them, modifying the code, both in the pico and the Arduino, also tried changing the antennas but nothing worked.
You have a buffer over-read - a major security flaw, same as the infamous Heartbleed bug.
When you pass a char * to Serial.println, it will print the data until it finds a null character. Your python string does not contain such null termination, so the the print function keeps going through the memory until it finds one. You were lucky that it found one quite quickly. It could also go on much longer, depending on what is in the memory at that time.
A naive way to fix the issue would be to just append a null character to the python string:
rfm9x.send("Hello World, this is a test, why does this not work? im going mad!!!!\0")
However, if you were to receive partial data (or someone forgot to add a null character), the issue would reappear.
The proper way to fix the problem is to check how much data is received and only print that much. According to the documentation, the received number of octets is stored in the len parameter. Therefore, you can add null-termination on the receiving end like so:
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
// Leave space for null-termination
uint8_t len = sizeof(buf) - 1;
if (rf95.recv(buf, &len))
{
// Add null-termination at the end of the received data.
buf[len] = '\0';
// Print as before.
digitalWrite(LED, HIGH);
Serial.print("Got: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC);
}
I'm writing a simple program for an Arduino that will take the input of 2 buttons and output simulated keys for 2 different functions to use in Clone Hero.
Arduino editor (both online and local versions) spit out
'Keyboard' was not declared in this scope
The offline editor asks if Keyboard.h is included... Which it obviously is.
Any ideas why?
// Keyboard - Version: Latest
#include <Keyboard.h>
//btnWhammy is the button to replace whammy bar function
//btnSP is the button to replace star power activation
//Set Clone Hero to register j for whammy and k for star power
//declaring constant integers for the pins on the Arduino
const int btnWhammy = 2;
const int btnSP = 13;
//Declaring integers for the state of the button press
int btnWhammyState = 0;
int btnSPState = 0;
void setup() {
//Initialisation of the pins as inputs
pinMode(btnWhammy, INPUT);
pinMode(btnSP, INPUT);
}
void loop() {
//Setting the button states to the read of the digital pin (LOW is off, HIGH is on)
btnWhammyState = digitalRead(btnWhammy);
btnSPState = digitalRead(btnSP);
//If the whammy button is pressed, send 'j' to the keyboard, wait 100ms then release all keys
if (btnWhammyState == HIGH) {
Keyboard.press('j');
delay(100);
Keyboard.releaseAll();
}
//If the Star Power button is pressed, send 'k' to the keyboard, wait 100ms then release all keys
if (btnSPState == HIGH) {
Keyboard.press('k');
delay(100);
Keyboard.releaseAll();
}
}
This is a classic mistake -- you are probably compiling for a non-Leonardo board, like a Uno. The Keyboard.h library is not included because it is not present for the board you are compiling with.
I took your code and compiled it for Leonardo -- no issues. For Uno, I get the same error as you...
keyboard key was not declared in this scope i found a very simple and working trick of this problem just go to your main file where you declare all other keys that you are facing not declare
#include <DigiKeyboard.h>
#define KEY_UP_ARROW 0x52
#define KEY_DOWN_ARROW 0x51
#define KEY_LEFT_ARROW 0x50
#define KEY_RIGHT_ARROW 0x4F
#define KEY_TAB 0x2B
I am trying to build a code in arduino, and am having an issue with getting it to compile. I am trying to build a monitor for my MPPT controller, it outputs via serial. i am able to receive the serial data to the pc through the arduino, and am now having an issue getting it to save values from the incomming serial information and store its value as a variable that i can call to perform other functions.
the serial data incomming into the pc is always the same, and is formatted like this
PID 0xA042
FW 123
SER# HQ155154LPY
V 0
I 0
VPV 0
PPV 0
CS 0
ERR 0
LOAD OFF
IL 0
H19 4438
H20 0
H21 0
H22 38
H23 136
HSDS 74
Checksum
and i need the values from the following fields
V, I,VPV,PPV,LOAD,H19,IL
the information is sent from the controller like this
Message format
The device transmits blocks of data at 1 second intervals. Each field is sent using the following format:
<Newline><Field-Label><Tab><Field-Value>
The identifiers are defined as follows:
Identifier Meaning
<Newline> A carriage return followed by a line feed (0x0D, 0x0A).
<Field-Label> An arbitrary length label that identifies the field. Where applicable, this will be the same as the label that is used on the LCD.
<Tab> A horizontal tab (0x09).
<Field-Value> The ASCII formatted value of this field. The number of characters transmitted depends on the magnitude and sign of the value.
Data integrity
The statistics are grouped in blocks with a checksum appended. The last field in a block will always be "Checksum". The value is a single byte, and will not necessarily be a printable ASCII character. The modulo 256 sum of all bytes in a block will equal 0 if there were no transmission errors. Multiple blocks are sent containing different fields.
this is the first time i have actualy tried to use serial for something other than simple debug/operation messages running in the code.
the code
/*
Odroid-SHOW MPPT Intrface Module
Reads information from MPPT controllers and displays it on the LCD, also outputs the information via SERIAL # 9600 BAUD
* **********PINOUTS********
MPPT Controller:
________________________
| 4 3 2 1 |
| . . . . |
| VCC TX RX GND |
| (RED) (YEL)(WHI)(BLK) |
| _______ |
|_______| |________|
Odroid SHOW:
5V - To VCC (RED) Pin (4)
A4 - To TX (YEL) Pin (3)
A5 - To RX (WHI) Pin (2)
GND - To GND (BLK) Pin (1)
*/
const char version[] = {"1.0 27/04/2017"};
//Below is the required Library inclusions
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include "TimerOne.h"
#include <Adafruit_GFX.h>
#include <ODROID_Si1132.h>
#include <ODROID_Si70xx.h>
#include <Adafruit_ILI9340.h>
//Below is the required Pin Defines and links for the TFT
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8
Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);
ODROID_Si70xx si7020;
ODROID_Si1132 si1132;
// Settings below are to control the Backlight brightness and rotation of the Odroid-SHOW LCD Display
uint8_t ledPin = 5;
uint8_t pwm = 255;
uint8_t textSize = 2;
uint8_t rotation = 1; //0 = Portrait, 1 = Landscape
//Below sets up the SoftwareSerial ports so that the arduino can receive information from the MPPT Controller aswell as pass its information through to the hardware UART
SoftwareSerial MPPTSERIAL(A4, A5); // RX, TX
void setup() {
// initialize the TFT and the digital pins for TFT backlight control
tft.begin();
si1132.begin();
initPins();
delay(50);
// Open serial communications on hardware UART and wait for port to open:
Serial.begin(9600);
delay(50);
//Below Prints the module Version information to both the Serial monitor and the TFT
Serial.println("Odroid-SHOW MPPT Intrface Module");
Serial.print("Module Firmware Version ");
Serial.println(version);
tft.fillScreen(ILI9340_BLACK);
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 25);
tft.print("Odroid-SHOW");
tft.setCursor(25, 45);
tft.print("MPPT Intrface Module");
tft.setCursor(25, 85);
tft.print("Module Firmware Version");
tft.setCursor(25, 105);
tft.print(version);
delay(2500);
// set the data rate for the SoftwareSerial port and print to TFT when initialized
MPPTSERIAL.begin(19200);
Serial.println("MPPT Serial Connection Initialized");
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 145);
tft.print("MPPT Serial");
tft.setCursor(25, 165);
tft.print("Connection Initialized");
delay(2500);
tft.fillScreen(ILI9340_BLACK);
}
void loop() {
if (MPPTSERIAL.available())
{
char inComing = MPPTSERIAL.read(); //read the available byte into a variable
String BattVoltage = getValue(inComing, "/n", 3).toString();
String PVCurrent = getValue(inComing, "/n", 4).toString();
String PVVoltage = getValue(inComing, "/n", 5).toString();
Serial.println(BattVoltage); //output the Battery Voltage to Serial Monitor
Serial.println(PVCurrent); //output the PV Charge Current to Serial Monitor
Serial.println(BattVoltage); //output the PV Voltage to Serial Monitor
tft.setRotation(rotation);
tft.setTextSize(textSize);
tft.setCursor(25, 25);
tft.print("Battery Voltage:")(BattVoltage); //output Battery Voltage to TFT
tft.setCursor(25, 145);
tft.print ("PV Current:")(PVCurrent); //output PV Charge Current to TFT
tft.setCursor(25, 165);
tft.print("PV Voltage:")(PVVoltage); //output PV Voltage to TFT
tft.fillScreen(ILI9340_BLACK);
}
if (Serial.available()) {
MPPTSERIAL.write(Serial.read());
}
}
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = { 0, -1 };
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
//Below is the various Function Calls
//This is the Backlight PWM control pin settings
void initPins(){
pinMode(ledPin, OUTPUT);
analogWrite(ledPin, pwm);
}
The IDE highlights these lines as the source of the error
String BattVoltage = getValue(inComing, "/n", 3).toString();
String PVCurrent = getValue(inComing, "/n", 4).toString();
String PVVoltage = getValue(inComing, "/n", 5).toString();
and that is giving me this error
converting to 'String' from initializer list would use explicit constructor 'String::String(char)'
from what i can gather, i may need to change it from a srting to an INT or a CHAR, but all the examples i have tried and just guessed out of hope have failed.
any pointers?
Jason
I have this RFID reader "Rosslare AY-X12", and it's working with Wiegand 26bit. I have an arduino mini Pro and connected together it's working fine but it only reads the card one time and then I have nothing.
When I put on the card arduino reads that card but only one time during the card is near by the reader and it again reads that card when I put off the card and then I put on. But I want to read that card continuously, I mean when the card is near by the Reader still reading the card, every 1ms reads that card.
Do you have any idea how to do that ? Is there any RFID arduino library which can do that? I had got the Mifare and its can do that. But this 125Khz reader which can communicate over Wiegand can't do that or I don't know how to do that.
I'm using this library : https://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino
My previous answer was deleted. I am going to make another attempt to answer the questions.
Do you have any idea how to do that ?
This cannot be done by Arduino because Arduino in your case is just reading the D0 and D1 pulses from your RFID reader. Since your RFID reader Rosslare AY-X12 does not send out continuous output of wiegand protocol, there is no way Arduino can read more than what was not sent to it.
The common RFID readers will not send continuous data of the same card because in the common use case (entry/exit/attendance), normally one tap is to check-in and another tap is to check-out. If the RFID reader sends continuous data of the same card, the main system receiving the multiple wiegand data will be confused and will not be able to determine if the user actually wish to check-in or check-out.
Is there any RFID arduino library which can do that?
No. There is no such RFID Arduino library. If the RFID reader is not sending out continuous data, there is no way the receiver (Arduino) can receive them.
Is there a way to achieve this?
Yes, there are some readers that has the option to turn on the continuous output of data, for example 714-52 MifareĀ® ID Reader with selectable outputs. In its specification :
Continuous output with tag in field or single transmission
With this reader configured to continuous output, you can then use Arduino and the monkeyboard wiegand library to read the data.
I wrote my own wiegand code. Its not that difficult. I attached interrupts to the data pins and when they change I log the zero or one. You then build up the binary string and once timed out because no bits coming in. Then you convert the binary to decimal.
#include <LiquidCrystal.h>
int data0 = 2; //set wiegand data 0 pin
int data1 = 3; //set wiegand data 1 pin
unsigned long bit_holder; //unsigned long (positive 32 bit number)
unsigned long oldbit = 0;
volatile int bit_count = 0;
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
unsigned long badge;
unsigned int timeout;
unsigned int t = 800;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("Present Badge");
delay(2);
Serial.println("Present Badge");
pinMode(data0, INPUT);
digitalWrite(data0, HIGH);
pinMode(data1, INPUT);
digitalWrite(data1, HIGH);
attachInterrupt(0, zero, FALLING); //attach interrupts and assign functions
attachInterrupt(1, one, FALLING);
}
void zero(){
bit_count ++;
bit_holder = (bit_holder << 1) + 0; //shift left one and add a 0
timeout = t;
}
void one(){
bit_count ++;
bit_holder = (bit_holder << 1) + 1; //shift left one and add a 1
timeout = t;
}
void loop() {
timeout --;
if (timeout == 0 && bit_count > 0){
lcd.clear();
lcd.print("Dec:");
lcd.print(bit_holder);
lcd.setCursor(0,1);
lcd.print("Hex:");
lcd.print(String(bit_holder,HEX));
Serial.print("bit count= ");
Serial.println(bit_count);
Serial.print("bits= ");
Serial.println(bit_holder,BIN);
oldbit = bit_holder; //store previous this value as previous
bit_count = 0; //reset bit count
bit_holder = 0; //reset badge number
}
}
You may need to find a reader that offer a continuously reading, as I know almost of Wiegand Reader in the market can't perform a continuously reading because they have a "onboard" control that controls this...
Maybe you can try with Arduino Serial RFID Reader...
try a this timer libary Timer1 and mayby try this code it worked for me, my tags and cards now reads continuously.
Greetings from Denmark
Gregor
#include <Timer1.h>
//******************************************************************
// ATmega168, ATmega328:
// - Using Timer 1 disables PWM (analogWrite) on pins 9 and 10
// ATmega2560:
// - Using Timer 1 disables PWM (analogWrite) on pins 11 and 12
// - Using Timer 3 disables PWM (analogWrite) on pins 2, 3 and 5
// - Using Timer 4 disables PWM (analogWrite) on pins 6, 7 and 8
// - Using Timer 5 disables PWM (analogWrite) on pins 44, 45 and 46
//******************************************************************
unsigned int lastTime;
#include <SoftwareSerial.h>
SoftwareSerial RFID = SoftwareSerial(2,4);
char character;
String our_id;
void setup()
{
// Disable Arduino's default millisecond counter (from now on, millis(), micros(),
// delay() and delayMicroseconds() will not work)
disableMillis();
// Prepare Timer1 to count
// On 16 MHz Arduino boards, this function has a resolution of 4us
// On 8 MHz Arduino boards, this function has a resolution of 8us
startCountingTimer1();
lastTime = readTimer1();
Serial.begin(9600);
RFID.begin(9600);
}
void loop()
{
unsigned int now = readTimer1();
while (RFID.available()>0)
{
character = RFID.read();
our_id += character;
lastTime = now;
}
if (our_id.length() > 10) {
our_id = our_id.substring(1,13);
Serial.println(our_id);
our_id = "";
}
delay(1000);
}