Overview
A barcode is a square or rectangular image consisting of a series of parallel black lines and white spaces of varying widths that can be read by a scanner. Barcodes are applied to products as a means of quick identification. They are used in retail stores as part of the purchase process, in warehouses to track inventory, and on invoices to assist in accounting, among many other uses.
In this tutorial we will make a simple Barcode Scanner that will display the barcode, product name and price in 3.5” TFT LCD display.
Here’s a sample video:
Hardware Components
You can buy it all here at CreateLabz.
Software Components
Application Discussion
Barcode Scanner
Is an electronic device that can read and output printed barcodes to a computer. Like a flatbed scanner, it consists of a light source, a lens and a light sensor translating for optical impulses into electrical signals.Additionally, nearly all barcode readers contain decoder circuitry analyzing the bar code’s image data provided by the sensor and sending the barcode’s content to the scanner’s output port.
How does it work:
A barcode scanner “scans” the black and white elements of a barcode by illuminating the code with a red light, which is then converted into matching text. More specifically, the sensor in the barcode scanner detects the reflected light from the illumination system (the red light) and generates an analog signal that is sent to the decoder. The decoder interprets that signal, validates the barcode using the check digit, and converts it into text.
USB Host Shield
USB Host Shield allows you to connect a USB device to your Arduino board. The Arduino USB Host Shield is based on the MAX3421E, which is a USB peripheral/host controller containing the digital logic and analog circuitry necessary to implement a full-speed USB peripheral or a full-/low-speed host compliant to USB specification rev 2.0. The shield is TinkerKit compatible, which means you can quickly create projects by plugging TinkerKit modules onto the board.
3.5” TFT LCD Shield
TFT LCD Shield contains a 16 bit color TFT screen with a large 3.5″ display and is designed to fit directly into the standard headers of an Arduino requiring no additional interface hardware. It support a relatively high resolution of 480 x 320 pixels.
Hardware Setup
1st Step: Mount the USB Host Shield on the Arduino Mega.
2nd Step: Connect the Barcode scanner to the USB Host Shield.
3rd Step: Mount the 3.5” TFT LCD Shield on the USB Host Shield.
Code
Libraries Included
Arduino Code
#include <usbhid.h> #include <usbcore.h> #include <usbhub.h> #include <hiduniversal.h> #include <hidboot.h> #include <SPI.h> #include <MCUFRIEND_kbv.h> MCUFRIEND_kbv tft; #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF #define GRAY 0x8410 #define CUSTOM1 0x1FBC #define CUSTOM2 0x1107 #define CUSTOM3 0xDEC1 uint16_t version = MCUFRIEND_KBV_H_; uint8_t ascii; uint8_t code[13]; int scancounter = 0; int def = 160; int reg = 0; int width; int height; class MyParser : public HIDReportParser { public: MyParser(); void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); protected: uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key); virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key); virtual void OnScanFinished(); }; MyParser::MyParser() {} void MyParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { // If error or empty, return if (buf[2] == 1 || buf[2] == 0) return; for (uint8_t i = 7; i >= 2; i--) { // If empty, skip if (buf[i] == 0) continue; // If enter signal emitted, scan finished if (buf[i] == UHS_HID_BOOT_KEY_ENTER) { Serial.println(reg); //--------------------------------------------------------------------// if (reg == 686) { Serial.println(" - Barcode "); Serial.print("Product name:"); Serial.println(" Sprite 300mL "); Serial.println((char)code[1]); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 60); tft.print("Barcode: "); for (int i = 1; i <= 13; i++) { c += 18; tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(def, 90); tft.print((char)code[i]); //Serial.print((char)code[i]); if (i == 13) { def = 160; } } tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 120); tft.print("Product: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 150); tft.print("Sprite 300mL"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 180); tft.print("Price: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 210); tft.print("Php 15.00"); } //-----------------------------------------------------------------------// else if (reg == 692 ) { Serial.println(" - Barcode "); Serial.print("Product name:"); Serial.println(" Kopiko Blanca "); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 60); tft.print("Barcode: "); for (int i = 1; i <= 13; i++) { c += 18; tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(def, 90); tft.print((char)code[i]); //Serial.print((char)code[i]); if (i == 13) { def = 160; } } tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 120); tft.print("Product: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 150); tft.print("kopiko Blanca"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 180); tft.print("Price: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 210); tft.print("Php 7.00"); } //--------------------------------------------------------------------------// else if (reg == 670 ) { Serial.println(" - Barcode "); Serial.print("Product name:"); Serial.println(" Nescafe Original "); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 60); tft.print("Barcode: "); for (int i = 1; i <= 13; i++) { c += 18; tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(def, 90); tft.print((char)code[i]); //Serial.print((char)code[i]); if (i == 13) { def = 160; } } tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 120); tft.print("Product: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 150); tft.print("Nescafe Original"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 180); tft.print("Price: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 210); tft.print("Php 7.00"); } OnScanFinished(); } // If not, continue normally else { // If bit position not in 2, it's uppercase words OnKeyScanned(i > 2, buf, buf[i]); } return; } } uint8_t MyParser::KeyToAscii(bool upper, uint8_t mod, uint8_t key) { // Letters if (VALUE_WITHIN(key, 0x04, 0x1d)) { if (upper) return (key - 4 + 'A'); else return (key - 4 + 'a'); } // Numbers else if (VALUE_WITHIN(key, 0x1e, 0x27)) { return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1'); } return 0; } void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) { ascii = KeyToAscii(upper, mod, key); scancounter++; code[scancounter] = ascii; reg += code[scancounter]; Serial.print(ascii); Serial.print((char)ascii); } void MyParser::OnScanFinished() { Serial.println(" - Finished"); reg = 0; scancounter = 0; } USB Usb; USBHub Hub(&Usb); HIDUniversal Hid(&Usb); MyParser Parser; void setup() { Serial.begin( 115200 ); Serial.println("Start"); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); width = tft.width(); height = tft.height(); tft.drawRect(0, 0, width, height, WHITE); tft.drawRect(32, 32, width - 64, height - 64, WHITE); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.fillCircle(240, 190, 60, CUSTOM3); tft.fillCircle(310, 130, 60, CUSTOM2); tft.fillCircle(170, 130, 60, CUSTOM1); tft.fillCircle(310, 240, 60, CUSTOM1); tft.fillCircle(170, 240, 60, CUSTOM2); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); if (Usb.Init() == -1) { Serial.println("OSC did not start."); } delay( 200 ); Hid.SetReportParser(0, &Parser); } void loop() { Usb.Task(); }
Code Breakdown
void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) { ascii = KeyToAscii(upper, mod, key); scancounter++; code[scancounter] = ascii; reg += code[scancounter]; Serial.print((char)ascii); }
This is the code where the barcode scanner will read the values stored in the barcode, and store it in an array. Then adds all the value and store it in the reg variable. And print it in serial monitor as a character.
void setup() { Serial.begin( 115200 ); Serial.println("Start"); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); width = tft.width(); height = tft.height(); tft.drawRect(0, 0, width, height, WHITE); tft.drawRect(32, 32, width - 64, height - 64, WHITE); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.fillCircle(240, 190, 60, CUSTOM3); tft.fillCircle(310, 130, 60, CUSTOM2); tft.fillCircle(170, 130, 60, CUSTOM1); tft.fillCircle(310, 240, 60, CUSTOM1); tft.fillCircle(170, 240, 60, CUSTOM2); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); if (Usb.Init() == -1) { Serial.println("OSC did not start."); } delay( 200 ); Hid.SetReportParser(0, &Parser); }
In this code we begin the serial communication and initialize the TFT screen and display the “Barcode Scanner” text and the design elements.
if (buf[i] == UHS_HID_BOOT_KEY_ENTER) { Serial.println(reg); //--------------------------------------------------------------------// if (reg == 686) { Serial.println(" - Barcode "); Serial.print("Product name:"); Serial.println(" Sprite 300mL "); Serial.println((char)code[1]); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 60); tft.print("Barcode: "); for (int i = 1; i <= 13; i++) { def += 18; tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(def, 90); tft.print((char)code[i]); //Serial.print((char)code[i]); if (i == 13) { def = 160; } } tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 120); tft.print("Product: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 150); tft.print("Sprite 300mL"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 180); tft.print("Price: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 210); tft.print("Php 15.00"); } //-----------------------------------------------------------------------// else if (reg == 692 ) { Serial.println(" - Barcode "); Serial.print("Product name:"); Serial.println(" Kopiko Blanca "); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 60); tft.print("Barcode: "); for (int i = 1; i <= 13; i++) { def += 18; tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(def, 90); tft.print((char)code[i]); //Serial.print((char)code[i]); if (i == 13) { def = 160; } } tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 120); tft.print("Product: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 150); tft.print("kopiko Blanca"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 180); tft.print("Price: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 210); tft.print("Php 7.00"); } //--------------------------------------------------------------------------// else if (reg == 670) { Serial.println(" - Barcode "); Serial.print("Product name:"); Serial.println(" Nescafe Original "); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(3); tft.fillScreen(CUSTOM1); tft.fillRoundRect(32, 50, width - 64, height - 64, 30, WHITE); tft.setTextSize(4); tft.setTextColor(CUSTOM2, WHITE); tft.setCursor(10, 10); tft.print("BARCODE SCANNER"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 60); tft.print("Barcode: "); for (int i = 1; i <= 13; i++) { def += 18; tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(def, 90); tft.print((char)code[i]); //Serial.print((char)code[i]); if (i == 13) { def = 160; } } tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 120); tft.print("Product: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 150); tft.print("Nescafe Original"); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(40, 180); tft.print("Price: "); tft.setTextSize(3); tft.setTextColor(WHITE, CUSTOM2); tft.setCursor(175, 210); tft.print("Php 7.00"); }
In this code, we identify if the scanning of the barcode is complete. And displays the sum of all the values in a barcode and if the sum of the all the values in the barcode is equal to a registered value, then it will displays the product name, price and barcode in the TFT LCD. And then calls the OnScanFinished() function.
void MyParser::OnScanFinished() { Serial.println(" - Finished"); reg = 0; scancounter = 0; }
In this code if the function is called it will just reset the value of the reg variable or set it back to zero and also the scancounter variable.
Important Note!
Standard-sized Arduino boards, such as Duemilanove and UNO have SPI signals routed to pins 11-13 in addition to ICSP connector, therefore shields using pins 11-13 combined with standard-sized Arduinos will interfere with SPI. And since we are using 3.5” TFT LCD Shield that uses 11-13 pins for SPI communication. So it would be better if we use an arduino board that doesn’t use the pins 11 -13 for SPI communication, like the arduino mega.
Conclusion
Barcodes eliminate the possibility of human. A barcode scan is fast and reliable, and takes less time than entering data by hand. So this tutorial can be a good help in doing business much more efficient, and you can also modify or upgrade it.
Reference
[1] https://www.circuitsathome.com/usb-host-shield-hardware-manual/
[2] http://www.waspbarcode.com/buzz/how-barcode-scanners-work/
[3] https://ee.hawaii.edu/~tep/EE160/Book/chap4/subsection2.1.1.1.html
The post Barcode Scanner using H1800 CCD Sensor 1D Scan Engine and USB Host Shield with 3.5” LCD appeared first on CreateLabz.