Hello.
I am new in this blog. I sometime use Arduino for various projects.
My latest idea developed this summer during holidays: "NO CODE NO PAPER", a system of queue management that does not require the use of paper. It has bothered me a long time to see printed unnecessarily.
For the system, I imagined a totem with a barcode reader, or, in order to be able to keep them around, I thought to use customer cards, the ones most people already have, those cards that collect points for things we all use (the pharmacy, distributor, shopping center, etc.).
The idea is that the customer, with his card or with a card of the dispenser, goes in to the totem for the reader, the player reads the text written in the barcode of the card and put it in the list queue showing in the monitor.
For the hardware I used1. Arduino Uno + USB Arduino Shield combined with a barcode reader, all serving to read the cards;
2. Arduino Mega + Arduino Ethernet Shield Ethernet + USB converter to the server system.
3. A tablet with Android as output units.
The function system as followsThe Arduino Mega board generates a web page for the tablet, reads the SD card CODAx.TXT the file containing the current (SD tail needed in case of a blackout), and press the on-screen tail. Below controls the serial port Serial1 on hold if the text comes from it.
The Arduino Uno board with USB Shield joined with the barcode reader will send the text detected by the reader to Serial1 the Arduino Mega.
For the project, I used two different Arduino boards in order not to complicate the whole thing. But during trials, I also checked out different solutions with Wifi, with the Arduino Mega as an Access Point, and Client Access with Arduino WiFi Shield. Though two different Arduino boards made it looks slimmer.
Hope you like it.
Camillo
#include <hidboot.h>
#include <usbhub.h>
String MyString = "";
int LenString = 0;
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
class KbdRptParser : public KeyboardReportParser
{
void PrintKey(uint8_t mod, uint8_t key);
protected:
void OnControlKeysChanged(uint8_t before, uint8_t after);
void OnKeyDown (uint8_t mod, uint8_t key);
void OnKeyUp (uint8_t mod, uint8_t key);
void OnKeyPressed(uint8_t key);
};
void KbdRptParser::PrintKey(uint8_t m, uint8_t key)
{
MODIFIERKEYS mod;
*((uint8_t*)&mod) = m;
};
void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
PrintKey(mod, key);
uint8_t c = OemToAscii(mod, key);
if (c)
OnKeyPressed(c);
}
void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
}
void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)
{
}
void KbdRptParser::OnKeyPressed(uint8_t key)
{
char inChar = (char)key;
if (key == 19) {
MyString += inChar;
Serial.println(MyString);
MyString = "";
}
else MyString += inChar;
};
USB Usb;
HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
uint32_t next_time;
KbdRptParser Prs;
void setup()
{
Serial.begin(115200);
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
if (Usb.Init() == -1)
delay( 200 );
next_time = millis() + 5000;
HidKeyboard.SetReportParser(0, (HIDReportParser*)&Prs);
}
void loop()
{
Usb.Task();
}
/*
Progetto Elimina Code SDCard e Ethernet
Questo modulo deve ricevere gli elementi della coda dalla seriale e scrivere nella SDCard e mostrarli nella pagina web.
*/
#include <SPI.h>
#include <SD.h>
#include <Ethernet.h>
#include <EEPROM.h>
#define maxLength 25
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 111);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
String inputString = ""; // conterr i caratteri provenienti dalla seriale
char* FileName[] = {"CodaUno.txt", "CodaDue.txt"}; // verr sostituito da CodaDue.txt a secondo se il file txt da usare
boolean stringComplete = false, CancellaElemento = false;
int CS_pin = 4;
int inCharFile;
String inputStringWEB = String(maxLength); // conterr i caratteri provenienti dal client
int NumeroFile; // contiene il numero del file nella non volatile memory (se CodaUno o CodaDue)
int IndirizzoMemoria = 0;
unsigned long TempoAttesa = millis(), TempoAttesaMedio = 1; // = 1 aggiungo un minuto per rendere piu' ragionevole il tempo di attesa
File myFile1, myFile2; // files di testo contenenti gli elementi della coda
File htmlFile; // ancora non usato "da cancellare"
void setup() {
pinMode(CS_pin, OUTPUT);
Serial.begin(115200);
Serial1.begin(115200);
inputString.reserve(200);
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
//Serial.print("server is at ");
//Serial.println(Ethernet.localIP());
if (!SD.begin(CS_pin)) {
//Serial.println("Avvio SD Card fallito!");
return;
}
//Serial.println("SD Card avviata.");
NumeroFile = int(EEPROM.read(IndirizzoMemoria)); // legge dalla memoria il file attivo se 0 o 1
if (NumeroFile > 1) {
NumeroFile = 0;
}
}
void loop() {
if ((Serial1.available() != 0) and (stringComplete == 0)) {
serialEvent();
}
if ((stringComplete) and (inputString.length()) >= 8) { // controllo stringhe provenienti dalla seriale scrivo i valori di corrente dei rispettivi canali.
// Scrittura del file
//Serial.println (inputString);
myFile1 = SD.open(FileName[NumeroFile], FILE_WRITE);
if (myFile1) {
//Serial.println("Mi preparo a scrivere il file .txt ...");
myFile1.println(inputString + "<br>");
myFile1.close();
//Serial.println("scrittura eseguita correttamente.");
}
else {
//Serial.println("Non stato possibile scrivere il file .txt!");
}
//Serial.println(inputString);
inputString = "";
stringComplete = false;
}
if (CancellaElemento) { // CancellaElemento se vero viene cancellato il primo elemento della coda
/* Cancella primo elemento dal file
Visto che non ho trovato una funzione capace di cancellare un elemento preciso del file ed inoltre non trovo funzioni per rinominare nomi dei file, allora
creo un blocco che trasferisce la coda senza l'elemento da cancellare in una nuova coda tipo CodaDue.txt, poi viene cancellato il vecchio file CodaUno.txt
e da questo momento la scheda lavora su CodaDue.txt, verranno invertiti i nomi dei files alla successiva richiesta di eliminazione primo elemento.*/
//Serial.println(NumeroFile);
if (NumeroFile == 0) {
myFile1 = SD.open(FileName[0], FILE_READ);
myFile2 = SD.open(FileName[1], FILE_WRITE);
if (myFile1) {
char inCharFile = (char)myFile1.read();
while (inCharFile != '>') { // legge tutti i caratteri del primo elemento della coda non fa nulla, il primo elemento si deve cancellare
inCharFile = (char)myFile1.read();
}
while (myFile1.available()) { //--- continua la lettura del file scrivendo i restanti elementi della coda nel nuovo file
myFile2.write(myFile1.read()); // myFile2.println(myFile1.read());
}
myFile1.close();
myFile2.close();
SD.remove(FileName[0]);
NumeroFile = 1;
EEPROM.write(IndirizzoMemoria, NumeroFile);
}
else {
//Serial.println("Non stato possibile aprire il file .txt!");
}
}
else {
myFile1 = SD.open(FileName[1], FILE_READ);
myFile2 = SD.open(FileName[0], FILE_WRITE);
if (myFile1) {
char inCharFile = (char)myFile1.read();
while (inCharFile != '>') { // legge tutti i caratteri del primo elemento della coda non fa nulla, il primo elemento si deve cancellare
inCharFile = (char)myFile1.read();
}
while (myFile1.available()) { //--- continua la lettura del file scrivendo i restanti elementi della coda nel nuovo file
myFile2.write(myFile1.read());
}
myFile1.close();
myFile2.close();
SD.remove(FileName[1]);
NumeroFile = 0;
EEPROM.write(IndirizzoMemoria, NumeroFile);
}
else {
//Serial.println("Non stato possibile aprire il file .txt!");
}
}
CancellaElemento = false;
}
inputStringWEB = "";
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
//Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// Serial.write(c); //stampa in carattere proveniente dal client
if (inputStringWEB.length() < maxLength) {
//inString.append(c);
inputStringWEB += c;
}
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec.
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html><head><style>table, th, td { border: 2px solid black; }</style></head><body><center>");
client.println("<img src=\"http://1.bp.blogspot.com/-Vk2Ril41e-w/UfaZiB2YweI/AAAAAAAABAk/1qHqsUmd_w4/s1600/intestazione%2Blunga.jpg\" style=\"width:550px;height:250px;\">");
//client.println("<h1 style=\"font-size:500%;\">Mio Turno</h1>");
client.println("<table>");
client.println("<tr>");
client.println("<h1 style=\"font-size:600%;\">");
client.print("Serviamo: ");
//--- questo blocco legge la prima stringa dal file e la stampa in rosso
myFile1 = SD.open(FileName[NumeroFile], FILE_READ);
if (myFile1) {
client.print("<font color=red>");
char inCharFile = (char)myFile1.read();
while (inCharFile != '>') {
client.write(inCharFile); //
inCharFile = (char)myFile1.read();
}
client.write(inCharFile); // stampa il carattere controllato '>'
client.println("</font>"); //-----------------------------------------------------------------------
if (inputStringWEB.indexOf("?") > -1) { // se vero ho ricevuto un comando get o post
client.println("<script>{window.open(\"http://192.168.1.111\", \"_self\");}</script>"); // carico nuovamente la pagina per cancellare inputStringWEB
//Serial.println("cancello il primo elemento della lista");
CancellaElemento = true;
TempoAttesa = millis() - (TempoAttesaMedio / 2);
}
else if (myFile1.available()!=2) {
client.print("<form method=get>");
client.println("<br><input name=\"S\" type=\"submit\" value=\"Prossimo: \">");
client.println("</form>");
}
//--- continua la lettura del file stampando i restanti elementi della coda in nero ---
while (myFile1.available()) {
if (myFile1.available() == 2) { // in pratica non serve, volevo eliminare l'ultimo carattere della pagina web
break;
}
else {
client.write(myFile1.read());
}
}
myFile1.close();
}
client.println("</h1>");
client.println("</tr>");
client.println("</table>");
//--- ----------------------------------------------------------------------------- ---
client.println("<h1 style=\"font-size:200%;\">");
client.println("<svg height=\"50\" width=\"800\"><line x1=\"0\" y1=\"0\" x2=\"1000\" y2=\"0\" style=\"stroke:rgb(255,0,0);stroke-width:12\" />");
client.println("--------------------------------------------------------------------------------------</svg><br>");
// calcolo il tempo d'attesa
client.println("Tempo di attesa medio: ");
TempoAttesaMedio = ((millis() - TempoAttesa) + TempoAttesaMedio) / 2;
client.println(((TempoAttesaMedio/999)/60) + 1); // +1 inserisco un offset di un minuto
client.println(" min<br>");
client.println("</h1>");
client.println("</center></body></html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
//Serial.println("client disconnected");
}
delay(1);
}
void serialEvent() {
while (Serial1.available()) {
char inChar = (char)Serial1.read();
if (('0' >= inChar <= '9') or ('A' >= inChar <= 'Z') or ('a' >= inChar <= 'z')) { // questo filtro fa in modo che inputString contenga solo caratteri da '0..9', 'A..Z' e 'a..z'
inputString += inChar;
}
delay(1);
if (Serial1.available() == 0) {
stringComplete = true;
}
}
}
Comments