No Code No Paper

No Code No Paper © GPL3+

Queue management system no paper.

  • 1,311 views
  • 0 comments
  • 2 respects

Components and supplies

About this project

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 used

1. 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 follows

The 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

Code

SKETCH FOR ARDUINO UNO + USB SHIELDArduino
#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();
  
}
SKETCH FOR ARDUINO MEGA + ETHERNET SHIELDArduino
/*
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;
    }
  }
}

Schematics

sketchNO CODE NO PAPER
No%20code%20no%20paper%20schema

Comments

Similar projects you might like

Blockly@rduino: Create Code with Blocks

Project tutorial by Team LibrEduc

  • 21,823 views
  • 12 comments
  • 93 respects

Arduino Morse Code Machine

Project showcase by Vlada Krsmanovic

  • 10,221 views
  • 1 comment
  • 30 respects

PlatformIO for Visual Studio Code

by formulahendry

  • 6,907 views
  • 0 comments
  • 17 respects

Straight Key Morse Code Oscillator

Project tutorial by AC8XU

  • 2,061 views
  • 0 comments
  • 3 respects

Monitoring the Fill Height of Paper Shredder

Project showcase by phpoc_man

  • 1,201 views
  • 5 comments
  • 18 respects

Morse Code Communication Using Laser Module (Both)

Project tutorial by SURYATEJA

  • 757 views
  • 0 comments
  • 8 respects
Add projectSign up / Login