Component | Description | QTY |
---|---|---|
ATTINY45 | IC AVR MCU 4K 10MHZ 8SOIC- | 3 |
609-5161-1-ND | 6 Positions Header Connector 0.100" SMD | 6 |
311-10.0KFRCT-ND | RES 10.0K OHM 1-4W 1% 1206 SMD | 3 |
311-499FRCT-ND | RES 499 OHM 1-4W 1% 1206 SMD | 3 |
311-0FRCT-ND | RES 0 OHM 1-4W 1% 1206 SMD | 1 |
445-1423-1-ND | CAP CER 1UF 50V X7R 10% 1206- | 3 |
Embedded electronics is all about interlinking circuits (processors or other integrated circuits) to create a symbiotic system. In order for those individual circuits to swap their information, they must share a common communication protocol. Hundreds of communication protocols have been defined to achieve this data exchange, and, in general, each can be separated into one of two categories: parallel or serial.
Parallel interfaces transfer multiple bits at the same time. They usually require buses of data - transmitting across eight, sixteen, or more wires. Data is transferred in huge, crashing waves of 1's and 0's.
Serial interfaces stream their data, one single bit at a time. These interfaces can operate on as little as one wire, usually never more than four.
Parallel communication certainly has its benefits. It's fast, straightforward, and relatively easy to implement. But it requires many more input/output (I/O) lines. If you've ever had to move a project from a basic Arduino Uno to a Mega, you know that the I/O lines on a microprocessor can be precious and few. So, we often opt for serial communication, sacrificing potential speed for pin real estate.
Asynchronous means that data is transferred without support from an external clock signal. This transmission method is perfect for minimizing the required wires and I/O pins, but it does mean we need to put some extra effort into reliably transferring and receiving data.
The asynchronous serial protocol has a number of built-in rules - mechanisms that help ensure robust and error-free data transfers, such as:
Wiring and Hardware: A serial bus consists of just two wires - one for sending data and another for receiving. As such, serial devices should have two serial pins: the receiver, RX, and the transmitter, TX.
It's important to note that those RX and TX labels are with respect to the device itself. So the RX from one device should go to the TX of the other, and vice-versa. It's weird if you're used to hooking up VCC to VCC, GND to GND, MOSI to MOSI, etc., but it makes sense if you think about it. The transmitter should be talking to the receiver, not to another transmitter.
// Including Libraries
#define DEBUG 1
#include
#include
#include
//FIXED WIFI Settings
#define ssid "Orange-D955" // WiFi SSID
#define password "IloveFLE" // WiFi password
// FIXED IP and NETWORK SETTINGS
IPAddress ip(192, 168, 1, 104);
//set static ip
IPAddress gateway(192, 168, 0, 1);
//set gateway
IPAddress subnet(255, 255, 255, 0);
//set subnet
ESP8266WebServer server ( 80 );
// INVENTORY ITEM NAMES, COUNT and QUANTITY
#define numberOfItems 12
String item[numberOfItems] = {
"ATtiny44",
"ATtiny45",
"20MHz_Oscillator",
"10k_Resistor",
"499_Resistor",
"LED_Red",
"LED_Blue",
"ATMega328p",
"1uF_Capacitor",
"Push_Buttons",
"AVR_ISP_Header",
"Male_Header_Pins"
}
;
byte itemQty[numberOfItems] = {
0,0,0,0,0,0,0,0,0,0,0,0
}; // DUMMY VARIABLE for storage
byte itemQtyS[numberOfItems] = {
10,13,5,18,6,9,3,2,12,14,16,20
}; // INITIAL COUNT when there is nothing in EEPROM, this is already saved now
// WEBPAGE CODE
// code was tested with notepad and browser(chrome)
// code written with help from bootstrap online demos and tutorials
// once code was ready, changed all double quotes to single quotes
// added variables for dynamic web page generation
String getPage(int boxNumber) {
String page = "< html lang='en'>";
page += "< html lang='en'>";
page += "< head>";
page += "< meta charset='utf-8'>";
page += "< meta http-equiv='X-UA-Compatible' content='IE=edge'>";
page += "< meta name='viewport' content='width=device-width, initial-scale=1'>";
page += "< title>Smart Drawer< /title>";
page += "< meta name='author' content='LayoutIt!'>";
page += "< link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'>";
page += "< script src='https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js'>< /script>";
page += "< script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'>< /script>";
page += " head>";
page += " < body>";
page += "< div class='container-fluid'>";
page += " < div class='row'>";
page += " < div class='col-md-12'>";
page += " < p>";
page += " < /p>";
page += " < /div>";
page += " < /div>";
page += " < div class='row'>";
page += " < div class='col-md-12'>";
page += " < div class='jumbotron'>";
page += " < h2>";
page += " Smart Drawer< /h2>";
page += " < h3>";
page += " Find and store components smartly< /h3>";
page += " < p>";
page += " Please type the component name in the below box";
page += " < /p>";
// SERACH BOX CODE - now removed.
//page += " < p>";
//page += " < form role='form' action='/' method='POST' class='form-inline'>";
//page += " < div class='form-group'>";
//page += " < label for='componentLabel'>";
//page += " SEARCH HERE: < /label>";
//page += " < input class='form-control' id='componentLabel' name='searchText'>";
//page += " < /div>";
//page += " < button type='submit' class='btn btn-primary'>";
//page += " Submit < /button>";
//page += " < /form>";
//page += " < /p>";
page += " < div class='row' style='margin-bottom:15px;'>";
page += " < form role='form' action='/' method='POST' class='form-inline'>";
page += " < div class='form-group'>";
page += " < label>Component Name:< /label>";
page += " < input type='text' id='search' name='search'>";
page += " < /div>";
page += " < button type='submit' class='btn btn-primary'>Search< /button>";
page += " < /form>";
if(boxNumber != -1)
{
page += "< div class='col-sm-4'>";
page += "< button type='button' class='btn btn-block btn-primary btn-lg' data-toggle='modal' data-target='#";
page += item[boxNumber];
page += "'>";
page += item[boxNumber];
page += " - Qty: ";
page += String(int(itemQty[boxNumber]));
page += "< /button>< /div>";
// Loop to generate code for MODAL/POPUP Boxes that appear when any button is clicked
// Generated DYNAMICALLY from variables in code
page += "< div id='";
page += item[boxNumber];
page += "' class='modal fade' role='dialog'>";
page += " < div class='modal-dialog'>";
page += " < div class='modal-content'>";
page += " < div class='modal-header'>";
page += " < button type='button' class='close' data-dismiss='modal'>× button>";
page += " < h4 class='modal-title'>";
page += item[boxNumber];
page += "< /h4>";
page += " < /div>";
page += " < div class='modal-body'>";
page += " < p>The Quantity of this item is = ";
page += String(int(itemQty[boxNumber]));
page += " < /p>";
page += " < p>";
page += " < form role='form' action='/' method='POST' class='form-inline'>";
page += " < div class='form-group'>";
page += " < label>Enter Quantity: label>";
page += " < input type='number' class='form-control bfh-number' data-zeros='true' value='0' name='qtyChange' />";
page += " < label class='radio-inline'>< input type='radio' name='add'>ADD< /label>";
page += " < label class='radio-inline'>< input type='radio' name='remove'>REMOVE label>";
page += " < input type='hidden' name='itemNumber' value='";
page += String(boxNumber);
page += " '/>";
page += " < /div>";
page += " < button type='submit' class='btn btn-primary'>LOCATE COMPONENT button>";
page += " < /form>";
page += " < /p>";
page += " < /div>";
page += " < /div>";
page += " < /div>";
page += "< /div>";
}
page += " < /div>";
page += " < /div>";
page += " < /div>";
page += "< /div>";
page += "< /body>";
page += "< /html>";
return page;
}
// function which manages how the page is shown to user and what operation is perfomed for inventory control.
void handleRoot() {
int itemNumber = 100, qtyChange = 0, sign = 1;
String search_value = "";
boolean search_v = false;
int search_index = -1;
if (server.args() > 0 ) {
if(DEBUG)
Serial.println("Server Arguments: ");
for ( int i = 0; i < server.args(); i++ ) {
if(DEBUG){
Serial.print(server.argName(i));
Serial.print(": ");
Serial.println(server.arg(i));
}
if (server.argName(i) == "search")
{
search_value = server.arg(i);
search_v = true;
}
if (server.argName(i) == "qtyChange")
qtyChange = server.arg(i).toInt();
if (server.argName(i) == "itemNumber")
itemNumber = server.arg(i).toInt();
if (server.argName(i) == "add")
sign = 1;
if (server.argName(i) == "remove")
sign = -1;
// if server argument is a valid add/remove number
// the item quantity is changed, saved in variable, showed to user and saved in EEPROM
if(itemNumber < numberOfItems) {
if(itemQty[itemNumber]+(qtyChange*sign)>=0){
itemQty[itemNumber] = itemQty[itemNumber]+(qtyChange*sign);
EEPROM.write(itemNumber, itemQty[itemNumber]);
EEPROM.commit();
}
Serial.println(itemNumber);
Serial.println(",");
}
}
}
if(search_v)
{
for (int z=0; z< numberOfItems; z++)
{
if(search_value == item[z])
{
search_index = z;
break;
}
}
server.send ( 200, "text/html", getPage(search_index));
}
else
server.send ( 200, "text/html", getPage(-1) );
}
int address = 0;
byte value;
void setup() {
// INITIALIZATION CODE, Serial, EEPROM, Server
delay(1000);
EEPROM.begin(512);
Serial.begin(115200);
delay(1000);
Serial.println(-1);
delay(1000);
Serial.println(-1);
// WRITE ALL DEFAULT VALUES TO EEPROM
// Serial.println("itemQtyS[z]");
// for(int z=0; z< numberOfItems; z++){
// address = z;
// EEPROM.write(address, itemQtyS[z]);
// Serial.println(itemQtyS[z]);
// address = address + 1;
// if (address == 512)
// {
// address = 0;
// EEPROM.commit();
// }
// }
// READ ITEM QUANTITY from EEPROM
if(DEBUG)
Serial.println("itemQtyREAD[z]");
for (int z=0; z< numberOfItems; z++) {
address = z;
itemQty[z] = EEPROM.read(address);
if(DEBUG)
Serial.println(itemQty[z]);
address = address + 1;
if (address == 512) {
address = 0;
EEPROM.commit();
}
}
// connect to WIFI and start WEB SERVER
if(DEBUG) {
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
}
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
if(DEBUG)
Serial.print(".");
}
if(DEBUG) {
Serial.println("");
Serial.println("WiFi connected");
}
delay(1000);
Serial.println(0);
server.begin();
if(DEBUG) {
Serial.println("Server started");
Serial.print("Type this address in URL to connect: ");
Serial.print("http://");
Serial.println(ip);
Serial.println("/");
}
// link to the function that manage launch page
server.on ( "/", handleRoot );
server.begin();
delay(1000);
Serial.println(1);
if(DEBUG)
Serial.println ( "HTTP server started" );
delay(1000);
Serial.println(2);
delay(1000);
Serial.println(-1);
delay(1000);
Serial.println(-1);
// TURN OFF ALL LEDS
// at start LEDs of boxes 1, 2 and 3 are turned on to indicate system status
// each step makes the other box LEDs turn on
// box 2 is wifi connected status
// box 3 is server start status
}
void loop() {
server.handleClient();
delay(500);
}
// LOOP code, keeps running forever.
// Original checked by Noor
// edited by Mahmoud Abo Elnaga
// Including Libraries
#include "FastLED.h"
#define NUM_LEDS 20
CRGB leds[NUM_LEDS];
#define PIN 6
// variable for which BOX LEDs to blink
byte ledToBlink = 0;
void setup()
{
Serial.begin(115200);
FastLED.addLeds(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
}
//Initialization PART.
// Starts the Serial Port, Controller waits for a NUMBER on the Serial Port to turn on the relevant LEDs of the selected BOX.
// RGB LED SUPPORT FUNCTIONS - from blog link: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
FastLED.show();
#endif
}
// RGB LED SUPPORT FUNCTIONS - for a single PIXEL - from blog link: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
#endif
}
// RGB LED SUPPORT FUNCTIONS - for all LEDs - from blog link: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
void setAll(byte red, byte green, byte blue) {
for(int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}
// LED EFFECT FUNCTION - from blog link: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
// MODIFIED to read SERIAL and ONLY show the relevant LED and the one before and after it.
// Each box has 3 LEDs, so the number received is multiplied by 3 and then the LED before it and after it is illuminated and rest are all set as color to BLACK.
void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
int Position=0;
for(int i=0; i0){
// ONLY TURN ON 3 LEDs and rest all set to BLACK==OFF
//if(i==ledToBlink-3 || i==ledToBlink-2 || i==ledToBlink-1)
if( i==ledToBlink-1 )
setPixel(i,((sin(i+Position) * 127 + 128)/255)*red,
((sin(i+Position) * 127 + 128)/255)*green,
((sin(i+Position) * 127 + 128)/255)*blue);
else
leds[i] = CRGB::Black;
}else{
leds[i] = CRGB::Black;
}
}
// CODE MODIFICATION END
showStrip();
delay(WaveDelay);
}
}
// LOOP FUNCTION, keeps the led effect running at all times
// LED effect changes color.
void loop() {
RunningLights(0xff,0,0, 50); // red
RunningLights(0,0xff,0, 50); // green
RunningLights(0,0,0xff, 50); // blue
RunningLights(0xff,0xff,0xff, 50); // white
// original checked by Noor
// further edits by Mahmoud Abo Elnaga
}