Guest User

Arduino

a guest
Jun 12th, 2017
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.97 KB | None | 0 0
  1. // JCM WB-13-SS ID-003, Bill Acceptor
  2. // Connected to Serial1 on Arduino Mega
  3. // Bill Acceptor 20 pin interface, TTL: pins 16 RX and 19 TX, 9600 bps 8E1
  4. // Arduino C++, written on www.codebender.cc
  5.  
  6. // By Jesse Campbell
  7. // January 2015
  8. // http://www.jbcse.com
  9.  
  10. #include <EEPROM.h>
  11. #include <Arduino.h>
  12. //#include "JCMBillAcceptorID003.h"
  13.  
  14. #ifndef _JCMBILLACCEPTORID003_
  15. #define _JCMBILLACCEPTORID003_
  16.  
  17. class JCMBillAcceptorID003{
  18.    
  19.     public:
  20.         boolean PRINT_BYTES;
  21.         boolean DEBUG;
  22.         boolean PAUSE_UNTIL_RX;
  23.         int WAIT_FOR_RESPONSE_DELAY;
  24.        
  25.         JCMBillAcceptorID003(HardwareSerial &hs): hardwareSerial(hs){
  26.            
  27.             if (&hardwareSerial == &Serial1){
  28.                 BILL_ACCEPTOR_RX = 19;
  29.                 BILL_ACCEPTOR_TX = 18;
  30.             }
  31.             else if (&hardwareSerial == &Serial2){
  32.                 BILL_ACCEPTOR_RX = 17;
  33.                 BILL_ACCEPTOR_TX = 16;
  34.             }
  35.             else if (&hardwareSerial == &Serial3){
  36.                 BILL_ACCEPTOR_RX = 15;
  37.                 BILL_ACCEPTOR_TX = 14;
  38.             }
  39.            
  40.             pinMode(BILL_ACCEPTOR_RX, INPUT);
  41.             digitalWrite(BILL_ACCEPTOR_RX, INPUT_PULLUP);
  42.             pinMode(BILL_ACCEPTOR_TX, INPUT);
  43.             digitalWrite(BILL_ACCEPTOR_TX, INPUT_PULLUP);
  44.            
  45.             billReceived = 0;
  46.             PRINT_BYTES = false;
  47.             DEBUG = false;
  48.             PAUSE_UNTIL_RX = false;
  49.             WAIT_FOR_RESPONSE_DELAY = 50;
  50.            
  51.             CASH_TOTAL_RECEIVED_EEPROM_ADDR = 0; // EEPROM address 0 to address 3; 4 bytes
  52.             BOOT_COUNT_EEPROM_ADDR = 4;
  53.            
  54.             hardwareSerial.begin(9600, SERIAL_8E1); //on bill acceptor TTL pins 16 RX and 19 TX
  55.         }
  56.        
  57.         void bootup(){
  58.             if (PAUSE_UNTIL_RX){ //pause until a char is sent to the serial port
  59.                 while(Serial.available() == 0);
  60.                 while(Serial.available()) Serial.read();
  61.             }
  62.            
  63.             increment(BOOT_COUNT_EEPROM_ADDR, 1);
  64.            
  65.             { byte req[] = {RESET}; beginTrans(req,sizeof(req)/sizeof(req[0])); }
  66.            
  67.            
  68.             //{ byte req[] = {STATUS_REQUEST}; beginTrans(req,sizeof(req)/sizeof(req[0])); }
  69.            
  70.            
  71.             { byte req[] = {SET_SECURITY_DENOMINATIONS,
  72.                            SECURITY_DENOMINATIONS_ALL_STANDARD,
  73.                            DATA_BYTE_UNUSED};
  74.                            beginTrans(req,sizeof(req)/sizeof(req[0]));
  75.             }
  76.             /*
  77.             { byte req[] = {SET_ENABLE_DISABLE_DENOMINATIONS,
  78.                             DENOMINATIONS_ALL, //DENOMINATIONS_ONES_FIVES,
  79.                             DATA_BYTE_UNUSED};
  80.                             beginTrans(req,sizeof(req)/sizeof(req[0]));
  81.             }
  82.             */
  83.             { byte req[] = {OPTIONAL_FUNCTION,
  84.                             OPTION1_HANGING & OPTION2_POWER_RECOVERY,
  85.                             DATA_BYTE_UNUSED};
  86.                             beginTrans(req,sizeof(req)/sizeof(req[0]));
  87.             }
  88.            
  89.            
  90.             //{ byte req[] = {VERSION_REQUEST}; beginTrans(req,sizeof(req)/sizeof(req[0])); }
  91.            
  92.            
  93.             //{ byte req[] = {CURRENCY_ASSIGNMENT}; beginTrans(req,sizeof(req)/sizeof(req[0])); }
  94.            
  95.             /*{ byte req[] = {BARCODE_FUNCTION,
  96.                             INTERLEAVED_TWO_OF_FIVE,
  97.                             NUMBER_OF_CHARACTERS};
  98.                             beginTrans(req,sizeof(req)/sizeof(req[0]));
  99.             }
  100.             */
  101.             { byte req[] = {BAR_INHIBIT,
  102.                             ENABLE_CURRENCY_ACCEPTANCE & DISABLE_BARCODE_TICKET_ACCEPTANCE};
  103.                             beginTrans(req,sizeof(req)/sizeof(req[0]));
  104.             }
  105.            
  106.             { byte req[] = {COMMUNICATION_MODE,
  107.                             POLLED};
  108.                             beginTrans(req,sizeof(req)/sizeof(req[0]));
  109.             }
  110.            
  111.             { byte req[] = {INHIBIT_ACCEPTOR,
  112.                             ENABLE_ACCEPTOR};
  113.                             beginTrans(req,sizeof(req)/sizeof(req[0]));
  114.             }
  115.            
  116.         }
  117.        
  118.         void setPaymentConfirmedCallback (void (*callbackFunction)(int amount)){
  119.             this->callbackFunction = callbackFunction;
  120.         }
  121.        
  122.         void poll(){
  123.             { byte req[] = {STATUS_REQUEST}; beginTrans(req,sizeof(req)/sizeof(req[0])); }
  124.             //t.update();
  125.         }
  126.        
  127.         void resetEEPROMCounters(){
  128.             resetCounter(CASH_TOTAL_RECEIVED_EEPROM_ADDR);
  129.             resetCounter(BOOT_COUNT_EEPROM_ADDR);
  130.             //Serial.println("Counters have been reset");
  131.         }
  132.        
  133.         unsigned long totalCashReceived(){
  134.             //Serial.print("Total cash: $");
  135.             return EEPROMReadlong(CASH_TOTAL_RECEIVED_EEPROM_ADDR);
  136.         }
  137.        
  138.         unsigned long bootCount(){
  139.             //Serial.print("Boot counter: ");  
  140.             return EEPROMReadlong(BOOT_COUNT_EEPROM_ADDR);
  141.         }
  142.     private:
  143.         static const byte STATUS_REQUEST = 0x11;
  144.         static const byte ACK = 0x50;
  145.         static const byte RESET = 0x40;
  146.         static const byte SET_SECURITY_DENOMINATIONS = 0xC1;
  147.         static const byte SECURITY_DENOMINATIONS_ALL_STANDARD = 0x82;
  148.         static const byte SET_ENABLE_DISABLE_DENOMINATIONS = 0xC0;
  149.         static const byte DENOMINATIONS_ALL = B00000000;
  150.         static const byte DENOMINATIONS_ONES_FIVES = B11111010; //0 is disable, 1 is enable; see pdf
  151.         static const byte OPTIONAL_FUNCTION = 0xC5;
  152.         static const byte VERSION_REQUEST = 0x88;
  153.         static const byte CURRENCY_ASSIGNMENT = 0x8A;
  154.         static const byte BARCODE_FUNCTION = 0xC6;
  155.         static const byte BAR_INHIBIT = 0xC7;
  156.         static const byte COMMUNICATION_MODE = 0xC2;
  157.         static const byte INHIBIT_ACCEPTOR = 0xC3;
  158.         static const byte ENABLED_IDLING = 0x11;
  159.         static const byte ACCEPTING = 0x12;
  160.         static const byte ESCROW = 0x13;
  161.         static const byte STACKING = 0x14;
  162.         static const byte VEND_VALID = 0x15;
  163.         static const byte STACKED = 0x16;
  164.         static const byte REJECTING = 0x17;
  165.         static const byte POWER_UP = 0x40;
  166.         static const byte VERSION_RESPONSE = 0x88;
  167.         static const byte INITIALIZING = 0x1B;
  168.         static const byte ONE_DOLLAR = 0x61;
  169.         static const byte FIVE_DOLLARS = 0x63;
  170.         static const byte TEN_DOLLARS = 0x64;
  171.         static const byte TWENTY_DOLLARS = 0x65;
  172.         static const byte FIFTY_DOLLARS = 0x66;
  173.         static const byte ONE_HUNDRED_DOLLARS = 0x67;
  174.         static const byte STACK_1 = 0x41;
  175.         static const byte INVALID_COMMAND = 0x4B;
  176.         static const byte DATA_BYTE_UNUSED = 0x00;
  177.         static const byte OPTION1_HANGING = 0x01;
  178.         static const byte OPTION2_POWER_RECOVERY = 0x02;
  179.         static const byte INTERLEAVED_TWO_OF_FIVE = 0x01;
  180.         static const byte NUMBER_OF_CHARACTERS = 0x12;
  181.         static const byte ENABLE_CURRENCY_ACCEPTANCE = 0x00;
  182.         static const byte DISABLE_CURRENCY_ACCEPTANCE = 0x01;
  183.         static const byte ENABLE_BARCODE_TICKET_ACCEPTANCE = 0x00;
  184.         static const byte DISABLE_BARCODE_TICKET_ACCEPTANCE = 0x02;
  185.         static const byte POLLED = 0x00;
  186.         static const byte INTERRUPT_MODE1 = 0x01;
  187.         static const byte INTERRUPT_MODE2 = 0x02;
  188.         static const byte ENABLE_ACCEPTOR = 0x00;
  189.         static const byte DISABLE_ACCEPTOR = 0x01;
  190.         static const byte INSERTION_ERROR_CROOKED = 0x71;
  191.         static const byte MAGNETIC_PATTERN_ERROR_CENTER = 0x72;
  192.         static const byte OTHER_SENSORS_DETECTED_SOMETHING = 0x73;
  193.         static const byte DATA_AMPLITUDE_ERROR = 0x74;
  194.         static const byte FEED_ERROR = 0x75;
  195.         static const byte DENOMINATION_ASSESSING_ERROR = 0x76;
  196.         static const byte PHOTO_PATTERN_ERROR_MARKS_TEARS = 0x77;
  197.         static const byte PHOTO_LEVEL_ERROR_DOUBLES_DIRTY = 0x78;
  198.         static const byte DISABLED_BY_DIP_SWITCH_OR_COMMAND = 0x79;
  199.         static const byte OPERATION_ERROR = 0x7B;
  200.         static const byte BILL_DETECTED_IN_TRANSPORT_ASSEMBLY_AT_WRONG_TIME = 0x7C;
  201.         static const byte LENGTH_ERROR = 0x7D;
  202.         static const byte COLOR_PATTERN_ERROR = 0x7E;
  203.         static const byte SYNC = 0xFC;
  204.         byte BILL_ACCEPTOR_RX;
  205.         byte BILL_ACCEPTOR_TX;
  206.         void (*callbackFunction)(int amount);
  207.         byte billReceived;
  208.         int CASH_TOTAL_RECEIVED_EEPROM_ADDR; // EEPROM address 0 to address 3; 4 bytes
  209.         int BOOT_COUNT_EEPROM_ADDR;
  210.         HardwareSerial &hardwareSerial;
  211.        
  212.         void beginTrans(byte request[], byte requestSize){
  213.             sendRequest(request, requestSize);
  214.             delay(WAIT_FOR_RESPONSE_DELAY); //each serial byte at 9600 bps adds 1 millisecond
  215.             processResponse(); 
  216.         }
  217.         void sendRequest(byte request[], byte requestSize){
  218.             byte temp[requestSize+2];
  219.            
  220.             temp[0] = SYNC;
  221.             temp[1] = requestSize+4;
  222.        
  223.             for(int i=0; i < requestSize; i++)
  224.                 temp[i+2] = request[i];
  225.            
  226.             int crcval = calcCRC(temp, sizeof(temp)/sizeof(temp[0]), 0);
  227.             //Serial.println(crcval);
  228.             byte crc[] = {crcval & 0xFF, crcval >> 8};
  229.            
  230.             if (PRINT_BYTES){
  231.                 Serial.print("H -> A, ");
  232.                 for(int i=0; i<sizeof(temp)/sizeof(temp[0]); i++){
  233.                     if (temp[i] < 0x16)
  234.                         Serial.print("0");
  235.                     Serial.print(temp[i], HEX);
  236.                     Serial.print(" ");
  237.                 }
  238.                
  239.                 for(int i=0; i<sizeof(crc)/sizeof(crc[0]); i++){
  240.                     if (crc[i] < 0x16)
  241.                         Serial.print("0");
  242.                     Serial.print(crc[i], HEX); 
  243.                     Serial.print(" ");
  244.                 }
  245.                 Serial.println();
  246.             }
  247.            
  248.             for(int i=0; i<sizeof(temp)/sizeof(temp[0]); i++)
  249.                 hardwareSerial.write(temp[i]);
  250.                
  251.             for(int i=0; i<sizeof(crc)/sizeof(crc[0]); i++)
  252.                 hardwareSerial.write(crc[i]);
  253.         }
  254.        
  255.         void processResponse(){
  256.            
  257.         //  while(hardwareSerial.available()){
  258.         //      int byteRead = hardwareSerial.read();
  259.         //      if (byteRead < 0x10)
  260.         //          Serial.print('0');
  261.         //      Serial.print(byteRead,HEX);
  262.         //      Serial.print(" ");
  263.         //  }
  264.         //  Serial.println();
  265.         //  return;
  266.            
  267.             byte bytesRead = 0;
  268.             byte responseSize = 0;
  269.        
  270.             while(hardwareSerial.available() == false);
  271.            
  272.             while(hardwareSerial.available()){
  273.                
  274.                 if (bytesRead == 0){
  275.                     byte first = (byte)hardwareSerial.read();
  276.                     //Serial.print("first ");
  277.                     //Serial.println(first, HEX);
  278.                     if (first != SYNC){
  279.                         if (DEBUG) {
  280.                             Serial.print("SYNC failed, ");
  281.                             Serial.print("byte received ");
  282.                             Serial.println(first, HEX);
  283.                         }
  284.                     }
  285.                 }
  286.                 else if (bytesRead == 1){
  287.                     responseSize = hardwareSerial.read();
  288.                     byte response[responseSize];
  289.                     response[0] = SYNC;
  290.                     response[1] = responseSize;
  291.                     //response[2] = hardwareSerial.read();
  292.                     //Serial.println(response[2]);
  293.                
  294.                     for(int i=2; i<responseSize; i++){
  295.                        
  296.                         if (Serial.available() == false)
  297.                             delay(10);
  298.                            
  299.                         response[i] = hardwareSerial.read();
  300.                         bytesRead++;
  301.                     }
  302.                     if (PRINT_BYTES){
  303.                         Serial.print("H <- A, ");
  304.                         for(int i=0; i<responseSize; i++){
  305.                             if (response[i] < 0x16)
  306.                                 Serial.print("0");
  307.                             Serial.print(response[i],HEX);
  308.                             Serial.print(" ");
  309.                         }
  310.                         Serial.println();
  311.                     }
  312.                    
  313.                     if (response[2] == ESCROW){
  314.                         if (response[3] == ONE_DOLLAR)
  315.                             billReceived = 1;
  316.                         else if (response[3] == FIVE_DOLLARS)
  317.                             billReceived = 5;
  318.                         else if (response[3] == TEN_DOLLARS)
  319.                             billReceived = 10;
  320.                         else if (response[3] == TWENTY_DOLLARS)
  321.                             billReceived = 20;
  322.                         else if (response[3] == FIFTY_DOLLARS)
  323.                             billReceived = 50;
  324.                         else if (response[3] == ONE_HUNDRED_DOLLARS)
  325.                             billReceived = 100;
  326.                         else
  327.                           if (DEBUG) Serial.println("exception, \"reversed\" bill code received, see pdf");
  328.                          
  329.                         //Serial.print("Bill received: $");
  330.                         //Serial.println(billReceived);
  331.                        
  332.                         { byte req[] = {STACK_1}; beginTrans(req,sizeof(req)/sizeof(req[0]));}
  333.                     }
  334.                     else if (response[2] == VEND_VALID){
  335.                         { byte req[] = {ACK}; sendRequest(req,sizeof(req)/sizeof(req[0]));} //don't listen for a response
  336.                         callbackFunction(billReceived);
  337.                         //Serial.println("Bill stored, dispense");
  338.                         increment(CASH_TOTAL_RECEIVED_EEPROM_ADDR, billReceived);
  339.                         billReceived = 0;
  340.                     }
  341.                     else if (response[2] == INVALID_COMMAND)
  342.                         if (DEBUG) Serial.println("reponded with received invalid command");
  343.                     else if (response[2] == REJECTING){
  344.                            if (DEBUG) Serial.println("rejecting bill, ");
  345.                            if (response[3] == INSERTION_ERROR_CROOKED);
  346.                              if (DEBUG) Serial.print("Insertion error (Crooked insertion)");
  347.                            else if (response[3] == MAGNETIC_PATTERN_ERROR_CENTER)
  348.                              if (DEBUG) Serial.print("Magnetic pattern error (Center)");
  349.                            else if (response[3] == OTHER_SENSORS_DETECTED_SOMETHING)
  350.                              if (DEBUG) Serial.print("While idle, a sensor other than the entrance sensors detected something.");
  351.                            else if (response[3] == DATA_AMPLITUDE_ERROR)
  352.                              if (DEBUG) Serial.print("Data amplitude error.");
  353.                            else if (response[3] == FEED_ERROR)
  354.                              if (DEBUG) Serial.print("Feed error");
  355.                            else if (response[3] == DENOMINATION_ASSESSING_ERROR)
  356.                              if (DEBUG) Serial.print("Denomination assessing error");
  357.                            else if (response[3] == PHOTO_PATTERN_ERROR_MARKS_TEARS)
  358.                              if (DEBUG) Serial.print("Photo pattern error (Marks, tears etc).");
  359.                            else if (response[3] == PHOTO_LEVEL_ERROR_DOUBLES_DIRTY)
  360.                              if (DEBUG) Serial.print("Photo level error (Sometimes caused by double notes or dirty bills)");
  361.                            else if (response[3] == DISABLED_BY_DIP_SWITCH_OR_COMMAND)
  362.                              if (DEBUG) Serial.print("Bill was disabled by DIP switch or command (Inhibit, direction).");
  363.                            else if (response[3] == OPERATION_ERROR)
  364.                              if (DEBUG) Serial.print("Operation error");
  365.                            else if (response[3] == BILL_DETECTED_IN_TRANSPORT_ASSEMBLY_AT_WRONG_TIME)
  366.                              if (DEBUG) Serial.print("A bill was detected in the transport assembly at the wrong time.");
  367.                            else if (response[3] == LENGTH_ERROR)
  368.                              if (DEBUG) Serial.print("Length error");
  369.                            else if (response[3] == COLOR_PATTERN_ERROR)
  370.                              if (DEBUG) Serial.print("Color pattern error.");  
  371.                     }
  372.                    
  373.                     int crcval = calcCRC(response, sizeof(response)/sizeof(response[0])-2, 0);
  374.                     //Serial.println(crcval);
  375.                     byte crc[] = {crcval & 0xFF, crcval >> 8};
  376.                    
  377.                     if (crc[0] != response[responseSize-2] || crc[1] != response[responseSize-1]){
  378.                         if (DEBUG) {
  379.                             Serial.println("message failed CRC check");
  380.                             Serial.print("crc[0] = ");
  381.                             Serial.print(crc[0],HEX);
  382.                             Serial.print(", crc[1] = ");
  383.                             Serial.print(crc[1],HEX);
  384.                             Serial.print(", response crc ");
  385.                             Serial.print(response[responseSize-2],HEX);
  386.                             Serial.print(" ");
  387.                             Serial.println(response[responseSize-1],HEX);
  388.                         }
  389.                     }
  390.                        
  391.                     if (responseSize != bytesRead+1)
  392.                         if (DEBUG) Serial.println("response length did not match stated length");
  393.                 }
  394.                 bytesRead++;
  395.             }
  396.        
  397.         }
  398.        
  399.         unsigned calcCRC(byte *data, unsigned n, unsigned start) {
  400.             unsigned I, k, q, c, crcval;
  401.             crcval=start;
  402.             for (I=0; I<n; I++) {
  403.                 c=data[I] & 0xFF;
  404.                 q=(crcval^c) & 0x0F;
  405.                 crcval=(crcval>>4)^(q*0x1081);
  406.                 q=(crcval^(c>>4)) & 0x0F;
  407.                 crcval=(crcval>>4)^(q*0x1081);
  408.             }
  409.             return crcval;
  410.         }
  411.        
  412.         void EEPROMWritelong(int address, unsigned long value){
  413.        
  414.             byte four = (value & 0xFF);
  415.             byte three = ((value >> 8) & 0xFF);
  416.             byte two = ((value >> 16) & 0xFF);
  417.             byte one = ((value >> 24) & 0xFF);
  418.            
  419.             EEPROM.write(address, four);
  420.             EEPROM.write(address + 1, three);
  421.             EEPROM.write(address + 2, two);
  422.             EEPROM.write(address + 3, one);
  423.         }
  424.        
  425.         unsigned long EEPROMReadlong(unsigned long address){
  426.             unsigned long four = EEPROM.read(address);
  427.             unsigned long three = EEPROM.read(address + 1);
  428.             unsigned long two = EEPROM.read(address + 2);
  429.             unsigned long one = EEPROM.read(address + 3);
  430.        
  431.             return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
  432.         }
  433.        
  434.         void increment(long address, byte amount){
  435.             EEPROMWritelong(address, EEPROMReadlong(address)+amount);
  436.         }
  437.        
  438.         void resetCounter(int address){
  439.             EEPROMWritelong(address, 0);   
  440.         }
  441.  
  442. };
  443.  
  444. #endif
Advertisement
Add Comment
Please, Sign In to add comment