220 Fun Projects with Arduino

6,587 2,164 113MB

English Pages [3101] Year 2020

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

220 Fun Projects with Arduino

Citation preview

220 Fun Projects with Arduino 1) Arduino Hacking STEM Electroconductivity Meter

COMPONENTS AND SUPPLIES biodegradable straw ×

1

×

2

coffee stir stick

stainless steel wire (28 gauge, 17cm)

×

2

×

2

×

1

×

1

×

1

pin-ended alligator clips Resistor 100 ohm

Arduino UNO & Genuino UNO

USB-A to B Cable

NECESSARY TOOLS AND MACHINES scissors Wire Stripper & Cutter, 18-10 AWG / 0.754mm² Capacity Wires

Hot glue gun (generic)

Tape, Clear

ruler

APPS AND ONLINE SERVICES Microsoft Data Streamer

Arduino IDE

Microsoft Excel

ABOUT THIS PROJECT This project aimed to meet the requirements of the science fair that happened in my city Our electroconductivity sensor was designed as a simple way to measure the amounts of dissolved substances in different water samples. It can also be used as a (short-term) soil moisture sensor! This sensor is made of two wires separated by an air gap. The air gap allows us to test how well a material or substance conducts electricity. Build an Electroconductivity Meter

Mark your straw at 14 cm. Cut at your mark.

Next, mark both of your coffee stir sticks at 13 cm and make cuts.

Using your hot glue gun, run a thin line of glue along the length of one of your stir sticks.

Quickly press the sticks together until the glue has cooled.

Measure and cut two lengths of 17 cm stainless steel wire. Straighten out the wires the best you can.

Place the wire on the stir stick so that it is centered and the ends extend about 1.75 cm beyond the stir stick.

Center your other wire opposite the first. Tape the wires onto the stir sticks.

Tape the middle and opposite ends of the sticks to hold the wire in place keeping the wires centered on the sticks.

Push the stir sticks with wire into your 14 cm straw.

Measure to make sure your wires stick out of the end of the straw at the 1.5 cm mark.

Dab some hot glue inside both ends of the straw.

Measure and cut your other length of straw at 4 cm

Cut the 4cm straw in half, then dab some hot glue on the end and...

... attach to the end of the straw! This will act as a shield guard for the sensor wire ends.

Bend the longer ends of the wire as shown in the photo above. This gives the alligator clips a better connection once attached.

Attach alligator clips to the bent wires. Awesome! You’ve completed the EC sensor. You care now ready to connect to your microcontroller. Connect your alligator clips to the Arduino Uno as shown in the Attachments section.

If you are comfortable writing Arduino code, use the analog input pins to measure the voltage changes across the EC sensor. You are also welcome to use our sketch which is provided in the Attachments section. SCHEMATICS A Fritzing Diagram showing the electrical connections from the EC Sensor wires to the Arduino analog input pin A0.

CODE // CONSTANTS / SETTINGS const byte const byte

POWER_PIN = 2; EC_PIN = A0;

// Digital pin to use for powering pulse circuit // Analog pin used to read EC Meter volage

const int const int

READ_DURATION = 100; READ_INTERVAL = 6000;

// Amount of time to take reading for (ms) // Amount of time between readings (ms)

const String SERIAL_OUTPUT_DELIMITER = ","; // Cordoba expects a commadelimited string const int SERIAL_OUTPUT_INTERVAL = 175; // Amount of time between serial outputs // TIMESTAMPS unsigned long currentTime = 0; unsigned long readStartTime = 0; unsigned long lastOutputTime = 0;

// Time that the EC Meter read process starts // Time of last serial output

// SENSORS float ecMeterReading = 0; float ecMeterVoltage = 0; void setup() { Serial.begin( 9600 ); pinMode( POWER_PIN , OUTPUT ); } void loop() { currentTime = millis(); // Read Sensors // Check for start read time if ( currentTime - readStartTime >= READ_INTERVAL ){ // Initialize EC Meter read sequence readStartTime = currentTime; // Set start time } else if ( currentTime - READ_DURATION "); } else if (modeAlarm == 1) { lcd.setCursor(0, 3); lcd.print("->"); } lcd.setCursor(2, 2); lcd.print("No"); lcd.setCursor(2, 3); lcd.print("Yes"); if (back) { back = 0; } else if (next) { if (modeAlarm == 0) { menuScreen = 2; } else if (modeAlarm == 1) { menuScreen = 1; } lcd.clear(); delay(500); next = 0; } else if (select) { if (modeAlarm == 0) {

menuScreen = 2; } else if (modeAlarm == 1) { menuScreen = 1; } lcd.clear(); delay(500); select = 0; } else if (up) { modeAlarm = modeAlarm - 1; if (modeAlarm < 0) { modeAlarm = 1; } delay(100); lcd.setCursor(0, 2); lcd.print(" "); lcd.setCursor(0, 3); lcd.print(" "); up = 0; } else if (down) { modeAlarm = modeAlarm + 1; if (modeAlarm > 1) { modeAlarm = 0; } delay(100); lcd.setCursor(0, 2); lcd.print(" "); lcd.setCursor(0, 3); lcd.print(" "); down = 0; } break; } } void menuScreen_SetAlarm() { switch (menuScreenTempAlarm) { case 0: lcd.setCursor(0, 0); lcd.print("Set the upper range"); lcd.setCursor(0, 1); lcd.print("T="); lcd.setCursor(3, 1);

lcd.print(upperTempAlarm, 1); lcd.print((char)223); lcd.print("C"); lcd.setCursor(0, 2); lcd.print("Press select to"); lcd.setCursor(0, 3); lcd.print("continue..."); if (back) { back = 0; lcd.clear(); delay(500); menuScreen = 0; } else if (next) { lowerTempCompAlarm = upperTempAlarm - 0.5; lowerTempAlarm = upperTempAlarm - 0.5; menuScreenTempAlarm = 1; lcd.clear(); delay(500); next = 0; } else if (select) { lowerTempCompAlarm = upperTempAlarm - 0.5; lowerTempAlarm = upperTempAlarm - 0.5; menuScreenTempAlarm = 1; lcd.clear(); delay(500); select = 0; } else if (up) { if (int_upperTempAlarm() >= 375) { upperTempAlarm = 37.5; lcd.setCursor(9, 1); lcd.print(" MAX TEMP"); delay(1000); lcd.setCursor(9, 1); lcd.print(" "); return; } upperTempAlarm = upperTempAlarm + 0.1; lcd.setCursor(3, 1); lcd.print(upperTempAlarm, 1); up = 0; } else if (down) { if (int_upperTempAlarm() = (int_upperTempAlarm() - 5)) { lowerTempAlarm = lowerTempCompAlarm; lcd.setCursor(9, 1); lcd.print(" MIN RANGE"); delay(1000); lcd.setCursor(9, 1); lcd.print(" "); return; } lowerTempAlarm = lowerTempAlarm + 0.1; lcd.setCursor(3, 1); lcd.print(lowerTempAlarm, 1); up = 0; } else if (down) { if (int_lowerTempAlarm() 1) { mode = 0; } delay(100); lcd.setCursor(0, 2); lcd.print(" "); lcd.setCursor(0, 3); lcd.print(" "); down = 0; } break; } } void Screen_Auto_intro() { lcd.setCursor(0, 0); lcd.print("This mode will try"); lcd.setCursor(0, 1); lcd.print("to stabilize the"); lcd.setCursor(0, 2); lcd.print("neonate temperature"); lcd.setCursor(0, 3); lcd.print("between 36.5 & 37.3"); delay(3000); lcd.clear(); lcd.setCursor(0, 0); lcd.print("The supervision of"); lcd.setCursor(0, 1); lcd.print("the neonate is "); lcd.setCursor(0, 2); lcd.print("mandatory at small"); lcd.setCursor(0, 3); lcd.print("lapses. 5~10 mins"); delay(3000); lcd.clear(); menuScreen = 5; } void menuScreen_Temp() {

switch (menuScreenTemp) { case 0: lcd.setCursor(0, 0); lcd.print("Set the upper range"); lcd.setCursor(0, 1); lcd.print("T="); lcd.setCursor(3, 1); lcd.print(upperTemp, 1); lcd.print((char)223); lcd.print("C"); lcd.setCursor(0, 2); lcd.print("Press select to"); lcd.setCursor(0, 3); lcd.print("continue..."); if (back) { back = 0; menuScreen = 0; } else if (next) { lowerTempComp = upperTemp - 1; lowerTemp = upperTemp - 1; menuScreenTemp = 1; lcd.clear(); delay(500); next = 0; } else if (select) { lowerTempComp = upperTemp - 1; lowerTemp = upperTemp - 1; menuScreenTemp = 1; lcd.clear(); delay(500); select = 0; } else if (up) { if (int_upperTemp() >= 370) { upperTemp = 37; lcd.setCursor(9, 1); lcd.print(" MAX TEMP"); delay(1000); lcd.setCursor(9, 1); lcd.print(" "); return; } upperTemp = upperTemp + 0.1;

lcd.setCursor(3, 1); lcd.print(upperTemp, 1); up = 0; } else if (down) { if (int_upperTemp() = (int_upperTemp() - 10)) { lowerTemp = lowerTempComp; lcd.setCursor(9, 1); lcd.print(" MIN RANGE"); delay(1000); lcd.setCursor(9, 1); lcd.print(" "); return; } lowerTemp = lowerTemp + 0.1; lcd.setCursor(3, 1); lcd.print(lowerTemp, 1); up = 0; } else if (down) { if (int_lowerTemp() upperTempAlarm) { digitalWrite(buzzer, HIGH); delay(150); digitalWrite(buzzer, LOW); delay(100); } } else { digitalWrite(buzzer, LOW); } } void buttonState() { back = digitalRead(button1); next = digitalRead(button2); select = digitalRead(button3); up = digitalRead(button4); down = digitalRead(button5); if (back == HIGH) { delay(150); } if (next == HIGH) { delay(150); } if (select == HIGH) { delay(150); } if (up == HIGH) { delay(150); } if (down == HIGH) { delay(150);

} } int int_upperTemp() { int int_upperTemp = upperTemp * 10; return int_upperTemp; } int int_lowerTemp() { int int_lowerTemp = lowerTemp * 10; return int_lowerTemp; } int int_midleRangeTemp() { int int_midleRangeTemp = midleRangeTemp * 10; return int_midleRangeTemp; } int int_coefWarmer() { int int_coefWarmer = coefWarmer * 10; return int_coefWarmer; } int int_upperTempAlarm() { int int_upperTempAlarm = upperTempAlarm * 10; return int_upperTempAlarm; } int int_lowerTempAlarm() { int int_lowerTempAlarm = lowerTempAlarm * 10; return int_lowerTempAlarm; }

6) Arduino Customizable Geiger Muller Counter

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO Can be any arduino device, does not have to be UNO DC-DC 1.5-3V to 300-400V 380V High Voltage Boost Step-up Voltage Inverter Module

×

1

Ideal final voltage is 400V, but can be from 350-450V (the power range of the GM tube).

×

1

×

1

×

1

STS-5 Geiger Muller Tube I found mine on ebay (less expensive). Be aware that you will likely have to buy from the Ukraine and it won't arrive for probably 2-3 weeks. SunFounder IIC I2C TWI Serial 2004 20x4 LCD Module Shield for Arduino Uno Mega2560 Flexibility on the unit. I used this LED display as had fewer wires involved going into it. Get a 20x4 and you will be fine.

NECESSARY TOOLS AND MACHINES Soldering iron (generic) Needed to create device matching to circuit board. Also required to solder the capacitor to the voltage transformer. Breadboard, 270 Pin My final project employed a solderable selfassembled circuit board, but if one is interested in a less permanent project, I found this to work as well.

ABOUT THIS PROJECT AS NOTED BY THE WORK OF ADNOVEA, THIS DEVICE USES HIGH VOLTAGES (400 V) THAT ARE DANGEROUS. WHILE CURRENTS ARE LOW, ANY AMOUNT OF CURRENT OR VOLTAGE INTRODUCED TO THE HUMAN BODY CAN INDUCE AN ARRHYTHMIA IN THE HEART THAT CAN STOP IT AND LEAD TO DEATH. PEOPLE WHO BUILD THIS PRODUCT SHOULD HAVE SOME EXPERIENCE WITH ELECTRONICS AND BE EXTREMELY MINDFUL OF APPROPRIATE SAFETY PRECAUTIONS WHILE USING THE HIGH VOLTAGE ASPECT OF THE CIRCUIT. My goal was to take the work of AdNovea and create a Geiger Muller counter that I had more freedom to program as I desired (the AdNovea work employed scripts that I was unable to find the appropriate program to modify). This would permit a user to both better understand the physics of the tube, but also create such a device that meets their project desires/needs. For the project, I simplified the circuit diagram from AdNovea to make

something more for what I was looking for: a personal counter that shows the counts, but not getting too complicated with ethernet connections and connection to national networks. I experimented with Bluetooth modules and buzzers and these can work with it, though I chose not to use them as I wanted more of a background radiation counter I could refer to when I wanted.

The construction is very straight forward (refer to circuit diagram). The only difficult aspects of this project was obtaining some of the parts (the GM tube and the high voltage converter). I purchased both of these items for little money on Ebay, but both were being sold from far away (the Ukraine and China respectively) so it took 3-4 weeks to receive the items.

I started with assembling the circuit on a bread board to best evaluate the circuit and where I could manipulate it to my desires. I assembled it per AdNovea's diagram, but left out the buzzer, ethernet module, and resistor leading to the GM tube (I was not getting sufficient current to the tube with that circuit design that prevented it from working). I then soldered it all onto a circuit board.

I have an Arduino uno cited here as what I used, but you could probably save space in a container by using a nano. I used electrical tape to attach the GM tube to the circuit board to save space as well as to cover the terminals on the voltage transformer to improve safety. As I have limited equipment to play around and drill holes with a plastic container to make something pretty like what AdNovea had, I used the cardboard box that I was given when I first purchased my Arduino circuit kit.

I did cut a hole in the top of the box so the LED display could fit snugly in there (and I further reinforced this with tape).

I also cut a hole in the side of the box to permit a USB cord to come in and power the device.

I attempted 9V batteries to start, but as expected, the batteries did not last long. Finally I put additional electric tape around the box/circuit board as needed at points where the circuit may come in contact with the cardboard to protect against fire and losing signal. The program I have designed for my project takes the counts collected by the GM tube every 30 seconds multiplied by 2 to provide an estimated counts per minute (measuring unit of GM tubes). I then used metric system conversions to report uSv/hr that is a more widely used reference measurement. As the device continues to run through this code, I had it report the average of the measurements that progressively were collected along with the standard error (SD / sqrt(n)). Statistically I chose standard error as ultimately what is collected is a sample from the mean background radiation levels making SE the more appropriate measure. Unfortunately due to the memory limitations of the Arduino, I was only able to create an array of measurements of 100 items

SCHEMATICS

CODE

#include #include unsigned long counts; //variable for GM Tube events unsigned long previousMillis; //variable for measuring time float averageCPM; float sdCPM; int currentCPM; float calcCPM; LiquidCrystal_I2C lcd(0x27, 20, 4); float CPMArray[100]; #define LOG_PERIOD 30000 // count rate (in milliseconds) void setup() { //setup counts = 0; currentCPM = 0; averageCPM = 0; sdCPM = 0; calcCPM = 0; lcd.init(); lcd.backlight(); Serial.begin(9600); pinMode(2, INPUT); attachInterrupt(digitalPinToInterrupt(2), impulse, FALLING); //define external interrupts } void loop() { //main cycle lcd.setCursor(0,2); lcd.print("CPM Count: "); lcd.print(counts); unsigned long currentMillis = millis(); if (currentMillis - previousMillis > LOG_PERIOD) { previousMillis = currentMillis; CPMArray[currentCPM] = counts * 2; lcd.clear(); lcd.setCursor(0,0); lcd.print("uSv/hr: ");

lcd.print(outputSieverts(CPMArray[currentCPM])); counts = 0; averageCPM = 0; sdCPM = 0; //calc avg and sd for (int x=0;x Arduino Due T_IRQ -> 22 T_DO -> 24 T_DIN -> 26 T_CS -> 28 T_CLK -> 30 For the display: Display -> Arduino Due SDO -> A.25 LED -> 3.3V SCK -> A.27 SDI -> A.26 DC -> 9 RESET -> 8

CS -> 10 GND -> GND VCC -> 3.3V

SCHEMATICS

CODE

///////////////////////////////////////////// // 2.8" TOUCH SCREEN TIC TAC TOE // // // // // // // // /////////////////////////////////////////////

//

#include #include #include #include #define TFT_RST 8 #define TFT_DC 9 #define TFT_CS 10 #define TOUCH_ORIENTATION LANDSCAPE Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); Adafruit_GFX_Button buttons[9]; URTouch myTouch(30, 28, 26, 24, 22); char start[10] = {"Gamestart"}; char you[4] = {"YOU"}; char cpu[4] = {"CPU"}; char again[7] = {"Again?"}; int player; int difficulty=8; unsigned short int x,y,b; // position touch #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F

#define YELLOW 0xFFE0 #define WHITE 0xFFFF int board[]={0,0,0,0,0,0,0,0,0};// holds position data 0 is blank, 1 human, 2 is computer unsigned turn; const unsigned char circle[]PROGMEM={ 0b0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7 0x0,0x0,0xf,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x7f 0x0,0x3,0xf8,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x3,0xf8,0x0,0x0,0x0,0xf,0xe0 0x0,0x3f,0x0,0x0,0x0,0x0,0x3f,0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x1f,0x0,0x0,0x0,0x7e,0x0 0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0xf8,0x0 0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0 0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0xf0,0x0 0x0,0xf8,0x0,0x0,0x0,0x0,0x7,0xc0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xf,0x80,0x0,0x0,0x7c, 0x0,0x3f,0x0,0x0,0x0,0x0,0x3f,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x7e,0x0,0x0,0x0,0xf,0xc0 0x0,0x3,0xf8,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x1,0xfe,0x0,0x0,0x1f,0xe0,0x0,0x0,0x0,0x0,0xff 0x0,0x0,0xf,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xf0,0x0,0x0,0x0,0x0,0x0,0x0 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }; const unsigned char x_bitmap[]PROGMEM={ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 0x1,0xff,0xff,0xe0,0x1,0xff,0xff,0xc0,0x0,0x1,0xff,0xff,0xf0,0x3,0xff,0xff,0xc0,0x0,0x0,0xff 0x0,0x3f,0xff,0xfc,0xf,0xff,0xfe,0x0,0x0,0x0,0x3f,0xff,0xfe,0x1f,0xff,0xfe,0x0,0x0,0x0,0x1f 0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,0x0,0x7,0xff,0xff,0xff,0xff,0xf0,0x0,0x0,0x0,0x3,0xff 0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x0,0x0, 0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x1f 0x0,0x0,0x3f,0xff,0xff,0xfe,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0xff 0x0,0x1,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x3, 0x0,0xf,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,0x0,0x1f,0xff,0xff,0x7f,0xff,0xfc,0x0,0x0,0x0,0x1f 0x0,0x7f,0xff,0xf8,0x1f,0xff,0xff,0x0,0x0,0x0,0xff,0xff,0xf8,0xf,0xff,0xff,0x80,0x0,0x0,0xff 0x3,0xff,0xff,0xc0,0x3,0xff,0xff,0xe0,0x0,0x3,0xff,0xff,0xc0,0x1,0xff,0xff,0xe0,0x0,0x0,0x0 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };

void setup() { myTouch.InitTouch(); myTouch.setPrecision(PREC_HI); tft.begin(); tft.setRotation(3); }

void loop() { int board[9] = {0,0,0,0,0,0,0,0,0}; drawStartScreen(); do{ myTouch.read(); x = myTouch.getX(); //Get touch point y = myTouch.getY(); delay(100); }while(!(buttons[0].contains(x,y))); tft.fillScreen(BLACK); //Draw white frame tft.drawRect(0,0,320,240,WHITE); //Print "Tic Tac Toe" Text tft.setCursor(30,30); tft.setTextColor(WHITE); tft.setTextSize(4); tft.print("Tic Tac Toe"); //Print "YouTube!" text tft.setCursor(30,100); tft.setTextColor(GREEN); tft.setTextSize(4); tft.print("Who begins"); //Create Red Button // create buttons // x, y, w, h, outline, fill, text buttons[0].initButton(&tft, 100,200,80,40,WHITE, RED, WHITE, you, 2); buttons[0].drawButton(); // create buttons // x, y, w, h, outline, fill, text buttons[1].initButton(&tft, 200,200,80,40,WHITE, RED, WHITE, cpu, 2); buttons[1].drawButton(); b=1; do{ myTouch.read(); x = myTouch.getX(); //Get touch point y = myTouch.getY(); if (buttons[0].contains(x,y)) { b=0; player = 1; tft.fillScreen(BLACK); //Draw white frame tft.drawRect(0,0,320,240,WHITE);

tft.setCursor(30,30); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print("Ok, you begin."); delay(2000); } if(buttons[1].contains(x,y)) { b=0; player = 2; tft.fillScreen(BLACK); //Draw white frame tft.drawRect(0,0,320,240,WHITE); tft.setCursor(30,30); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print("Ok, CPU begins."); delay(2000); } }while(b); tft.fillScreen(BLACK); tft.drawRect(0,0,319,240,WHITE); drawVerticalLine(125); drawVerticalLine(195); drawHorizontalLine(80); drawHorizontalLine(150); for(turn = 0; turn < 9 && win(board) == 0; ++turn) { if((turn+player) % 2 == 0) computerMove(board); else { //draw(board); playerMove(board); } } switch(win(board)) { case 0: Serial.println("It's a draw.\n"); break; case 1: //draw(board); Serial.println("You lose.\n"); break; case -1:

Serial.println("You win!\n"); break; } do{}while(myTouch.dataAvailable()==false); //x = map(tp.y, 930, 88, 0, 480); //y = map(tp.x, 908, 125, 0, 320); //delay(250);} } void drawHorizontalLine(int y) { int i=0; for(i=0;i= read_sens_Interval) { // time is up, so read sensors previous_sens_Millis = currentMillis; // because shooter and Koepel told me so.// save the time we last read sensors sensLreading = analogRead(sens_L_Pin); // read left ldr (high value means the light is off or blockt) sensRreading = analogRead(sens_R_Pin); // read right ldr (high value means the light is off or blockt) if (sensLreading > 200 && direct == HIGH) { train reached left gate*** digitalWrite(led_L_Pin, LOW); digitalWrite(led_R_Pin, HIGH); state = STATE_DECELERATE; previous_Dec_Millis = currentMillis; current time } if (sensRreading > 200 && direct == LOW) {

// if conditions are throu, the // turn left LED off // turn right LED on // set state to "decelerate" // set previous_Dec_Millis to

// if conditions are throu, the

train reached right gate*** digitalWrite(led_R_Pin, LOW); // turn right LED off digitalWrite(led_L_Pin, HIGH); // turn left LED on state = STATE_DECELERATE; // set state to "decelerate" previous_Dec_Millis = currentMillis; // set previous_Dec_Millis to current time } } } //======================================== void Start() { digitalWrite(led_L_Pin, HIGH); // turn left led on digitalWrite(brake_Pin, LOW); // Disengage the Brake digitalWrite(direction_Pin, direct); // Establishes direction of the train state = STATE_ACCELERATE; // set state to "accelerate" previous_Acc_Millis = currentMillis; // set previous_Acc_Millis to current time } //======================================== void Accelerate() { if (currentMillis - previous_Acc_Millis >= motor_Acc_Interval) { // check interval time previous_Acc_Millis = currentMillis; // because shooter and Koepel told me so.//last time of acceleration step Speed = Speed + 1; // add 1 to speed analogWrite(motor_Pin, Speed); // send Speed to motor_Pin if (Speed == max_Speed) { // if speed reach max speed state = STATE_RUN; // set state to "run" } } } //======================================== void Decelerate() { if (currentMillis - previous_Dec_Millis >= motor_Dec_Interval) { // check interval time previous_Dec_Millis = currentMillis; // because shooter and Koepel told me so.//last time of acceleration step Speed = Speed - 1; // subtract 1 of speed analogWrite(motor_Pin, Speed); // send Speed to motor_Pin if (Speed == 0) { // if speed reach 0 state = STATE_TURN; // set state to "turn" }

} } //======================================== void Turn() { if (direct == HIGH) { // flip direction direct = LOW; digitalWrite(direction_Pin, direct); // establishes right direction of train } else { direct = HIGH; digitalWrite(direction_Pin, direct); // establishes left direction of train } state = STATE_ACCELERATE; // set state to "accelerate" previous_Acc_Millis = currentMillis; // set previous_Acc_Millis to current time } //========================================END

16) Arduino LED Rotation Display

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO Or any compatible (i used sainsmart mega 2560)

×

1

ABOUT THIS PROJECT For the development of this project it is necessary: * 1 x 12V DC Motor * 10 x RGB LEDs or LED diode * Arduino board * configuration * 9V battery * Photo diode Let's begin: photo diode refistruje when it crossed over the LEDs and thus knows that he visited one round.

On the motor shaft you find the card that is attached Arduino control unit "MEGA 2650". On the Arduino Mega little need to connect shield with RGB LEDs.

Shield with RGB LEDs containing 10 LEDs which is connected to a GND pins are distributed across the board to the contacts that go to pins 24 to 52 in the Arduino Mega

Coupled looks like

SCHEMATICS

CODE

Arduino code Led diode /*Arduino team politehnika Led display vazdušni */ int StartPin=A0; int t=1700; void setup(){

pinMode(2,OUTPUT); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(6,OUTPUT); pinMode(11,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(10,OUTPUT); } void loop(){ int val=analogRead(StartPin); while(val < 200){ O(); A(); C();

val=analogRead(StartPin); } } void A(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,0,0,0,0,0,0,0); signal(1,0,1,1,1,1,1,1,1); signal(0,1,1,1,0,1,1,1,1); signal(0,1,1,1,0,1,1,1,1); signal(1,0,1,1,0,1,1,1,1); signal(1,1,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void B(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,0,0,0,1); signal(0,0,0,0,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void C(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(1,0,0,0,0,0,0,0,1); signal(1,1,1,1,1,1,1,1,1);

delay(t); } void D(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,0,0,0,0,0,1,1); signal(1,0,1,1,1,1,1,0,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void E(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void Fa(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(0,1,1,0,1,1,1,1,1); signal(0,1,1,0,1,1,1,1,1); signal(0,1,1,0,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void G(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,0,1,1,1); signal(1,0,1,1,1,0,0,0,1); signal(0,1,1,1,1,0,1,1,0); signal(0,1,1,1,1,0,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(1,0,0,0,0,0,0,0,1); signal(1,1,1,1,1,1,1,1,1); delay(t); } void H(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0);

signal(1,1,1,0,0,1,1,1,1); signal(1,1,1,0,0,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void I(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(0,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void J(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,0,0,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void K(){//LOW=1 HIGH=0 signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,1,1,1,0,0,0); signal(1,1,1,0,1,0,1,1,1); signal(1,1,1,1,0,1,1,1,1); signal(1,1,1,1,0,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void L(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void M(){ signal(1,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,0,0,0,0);

signal(0,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(1,0,0,0,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void N(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,1,0,1,1); signal(1,1,1,1,1,0,1,1,1); signal(1,1,1,1,0,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void O(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void P(){ signal(1,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,1,1,1,1); signal(0,1,1,1,1,0,1,1,1); signal(0,1,1,1,1,0,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delay(t); } void R(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,0); signal(1,0,0,0,0,1,1,0,1); signal(0,1,1,1,1,0,0,1,1); signal(0,1,1,1,1,0,1,1,1); signal(0,0,0,0,0,0,0,0,0);

signal(1,1,1,1,1,1,1,1,1); delay(t); } void S(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); delay(t); } void T(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(0,1,1,1,1,1,1,1,1); signal(0,0,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); delay(t); } void U(){ signal(1,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,0,0,1,1); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,0,1); signal(1,0,0,0,0,0,0,1,1); signal(1,1,1,1,1,1,1,1,1); delay(t); } void V(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,1,1,1,1,1); signal(1,1,1,1,1,0,1,1,1); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,0,1,1,1); signal(0,0,0,0,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); }

void Z(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,0,1); signal(0,0,1,1,1,1,1,0,1); signal(0,1,0,1,1,1,1,0,1); signal(0,1,1,0,1,1,1,0,1); signal(0,1,1,1,0,1,1,0,1); signal(0,1,1,1,1,0,0,0,1); signal(1,1,1,1,1,1,1,1,1); } void signal(int a,int b,int c,int d,int e,int f,int p,int k,int n){ /*Napomena 1=LOW 0=HIGH*/ if(a==1)digitalWrite(2,LOW); else digitalWrite(2,HIGH); if(b==1)digitalWrite(3,LOW); else digitalWrite(3,HIGH); if(c==1)digitalWrite(4,LOW); else digitalWrite(4,HIGH); if(d==1)digitalWrite(5,LOW); else digitalWrite(5,HIGH); if(e==1)digitalWrite(6,LOW); else digitalWrite(6,HIGH); if(f==1)digitalWrite(11,LOW); else digitalWrite(11,HIGH); if(p==1)digitalWrite(8,LOW); else digitalWrite(8,HIGH); if(k==1)digitalWrite(9,LOW); else digitalWrite(9,HIGH); if(n==1)digitalWrite(10,LOW); else digitalWrite(10,HIGH); delay(t); }

Arduino code RGB led /*Arduino team politehnika Led display vazdušni */ int StartPin=A0; int t=2000; void setup(){ //Red pins leds dioda

pinMode(28,OUTPUT); pinMode(45,OUTPUT); pinMode(33,OUTPUT); pinMode(46,OUTPUT); pinMode(34,OUTPUT); pinMode(51,OUTPUT); pinMode(39,OUTPUT); pinMode(52,OUTPUT); pinMode(40,OUTPUT); //Green pins leds dioda pinMode(29,OUTPUT); pinMode(42,OUTPUT); pinMode(30,OUTPUT); pinMode(47,OUTPUT); pinMode(35,OUTPUT); pinMode(48,OUTPUT); pinMode(36,OUTPUT); pinMode(53,OUTPUT); pinMode(41,OUTPUT); //Blue pins leds dioda pinMode(26,OUTPUT); pinMode(43,OUTPUT); pinMode(31,OUTPUT); pinMode(44,OUTPUT); pinMode(32,OUTPUT); pinMode(49,OUTPUT); pinMode(37,OUTPUT); pinMode(50,OUTPUT); pinMode(38,OUTPUT); } void loop(){ int val=analogRead(StartPin); while(val < 200){ O(); AAA(); CC();

val=analogRead(StartPin); } } void A(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,0,0,0,0,0,0,0); signal(1,0,1,1,1,1,1,1,1); signal(0,1,1,1,0,1,1,1,1); signal(0,1,1,1,0,1,1,1,1); signal(1,0,1,1,0,1,1,1,1); signal(1,1,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void B(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,0,0,0,1); signal(0,0,0,0,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0);

signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void C(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(1,0,0,0,0,0,0,0,1); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void D(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,0,0,0,0,0,1,1); signal(1,0,1,1,1,1,1,0,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void E(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,1,1,1,0,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void Fa(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(0,1,1,0,1,1,1,1,1); signal(0,1,1,0,1,1,1,1,1); signal(0,1,1,0,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void G(){ signal(1,1,1,1,1,1,1,1,1);

signal(1,1,1,1,1,0,1,1,1); signal(1,0,1,1,1,0,0,0,1); signal(0,1,1,1,1,0,1,1,0); signal(0,1,1,1,1,0,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(1,0,0,0,0,0,0,0,1); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void H(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,0,0,1,1,1,1); signal(1,1,1,0,0,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void I(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(0,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void J(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,0,0,1); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void K(){//LOW=1 HIGH=0 signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,1,1,1,0,0,0); signal(1,1,1,0,1,0,1,1,1); signal(1,1,1,1,0,1,1,1,1); signal(1,1,1,1,0,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void L(){

signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void M(){ signal(1,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,0,0,0,0); signal(0,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(1,0,0,0,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void N(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,1,0,1,1); signal(1,1,1,1,1,0,1,1,1); signal(1,1,1,1,0,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void O(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,1,1,1,1,1,1,1,0); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void P(){ signal(1,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,1,1,1,1); signal(0,1,1,1,1,0,1,1,1);

signal(0,1,1,1,1,0,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void R(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,0); signal(1,0,0,0,0,1,1,0,1); signal(0,1,1,1,1,0,0,1,1); signal(0,1,1,1,1,0,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void S(){ signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void T(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,1,1); signal(0,0,0,0,0,0,0,0,0); signal(0,1,1,1,1,1,1,1,1); signal(0,0,1,1,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void U(){ signal(1,1,1,1,1,1,1,1,1); signal(1,0,0,0,0,0,0,1,1); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,0,1); signal(1,0,0,0,0,0,0,1,1); signal(1,1,1,1,1,1,1,1,1); delayMicroseconds(t);

} void V(){ signal(1,1,1,1,1,1,1,1,1); signal(0,0,0,0,1,1,1,1,1); signal(1,1,1,1,1,0,1,1,1); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,1,1,1,0); signal(1,1,1,1,1,1,1,0,1); signal(1,1,1,1,1,0,1,1,1); signal(0,0,0,0,1,1,1,1,1); signal(1,1,1,1,1,1,1,1,1); } void Z(){ signal(1,1,1,1,1,1,1,1,1); signal(0,1,1,1,1,1,1,0,1); signal(0,0,1,1,1,1,1,0,1); signal(0,1,0,1,1,1,1,0,1); signal(0,1,1,0,1,1,1,0,1); signal(0,1,1,1,0,1,1,0,1); signal(0,1,1,1,1,0,0,0,1); signal(1,1,1,1,1,1,1,1,1); } void AA(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,0,0,0,0,0,0,0); signal1(1,0,1,1,1,1,1,1,1); signal1(0,1,1,1,0,1,1,1,1); signal1(0,1,1,1,0,1,1,1,1); signal1(1,0,1,1,0,1,1,1,1); signal1(1,1,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void BB(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,0,0,0,1); signal1(0,0,0,0,0,1,1,1,0); signal1(0,1,1,1,0,1,1,1,0); signal1(0,1,1,1,0,1,1,1,0); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void CC(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,0);

signal1(0,1,1,1,1,1,1,1,0); signal1(0,1,1,1,1,1,1,1,0); signal1(0,1,1,1,1,1,1,1,0); signal1(1,0,0,0,0,0,0,0,1); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void DD(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,0,0,0,0,0,1,1); signal1(1,0,1,1,1,1,1,0,1); signal1(0,1,1,1,1,1,1,1,0); signal1(0,1,1,1,1,1,1,1,0); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void EE(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,0); signal1(0,1,1,1,0,1,1,1,0); signal1(0,1,1,1,0,1,1,1,0); signal1(0,1,1,1,0,1,1,1,0); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void FF(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,1); signal1(0,1,1,0,1,1,1,1,1); signal1(0,1,1,0,1,1,1,1,1); signal1(0,1,1,0,1,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void GG(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,0,1,1,1); signal1(1,0,1,1,1,0,0,0,1); signal1(0,1,1,1,1,0,1,1,0); signal1(0,1,1,1,1,0,1,1,0); signal1(0,1,1,1,1,1,1,1,0); signal1(1,0,0,0,0,0,0,0,1); signal1(1,1,1,1,1,1,1,1,1);

delayMicroseconds(t); } void HH(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,0,0,1,1,1,1); signal1(1,1,1,0,0,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void II(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,0); signal1(0,0,0,0,0,0,0,0,0); signal1(0,1,1,1,1,1,1,1,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void JJ(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,0,0,1); signal1(0,1,1,1,1,1,1,1,0); signal1(0,1,1,1,1,1,1,1,0); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void KK(){//LOW=1 HIGH=0 signal1(1,1,1,1,1,1,1,1,1); signal1(0,0,0,1,1,1,0,0,0); signal1(1,1,1,0,1,0,1,1,1); signal1(1,1,1,1,0,1,1,1,1); signal1(1,1,1,1,0,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void LL(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,0); signal1(1,1,1,1,1,1,1,1,0); signal1(1,1,1,1,1,1,1,1,0); signal1(1,1,1,1,1,1,1,1,0); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1);

delayMicroseconds(t); } void MM(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,0,0,0,0,0,0,0,0); signal1(0,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,1); signal1(1,0,0,0,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,1); signal1(1,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void NN(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,0,1); signal1(1,1,1,1,1,1,0,1,1); signal1(1,1,1,1,1,0,1,1,1); signal1(1,1,1,1,0,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void OO(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(0,1,1,1,1,1,1,1,0); signal1(0,1,1,1,1,1,1,1,0); signal1(0,1,1,1,1,1,1,1,0); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void PP(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,0,0,0,0,1,1,1,1); signal1(0,1,1,1,1,0,1,1,1); signal1(0,1,1,1,1,0,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void RR(){ signal1(1,1,1,1,1,1,1,1,1);

signal1(1,1,1,1,1,1,1,1,0); signal1(1,0,0,0,0,1,1,0,1); signal1(0,1,1,1,1,0,0,1,1); signal1(0,1,1,1,1,0,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } /*void SS(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); }*/ void TT(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,0,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,1,1); signal1(0,0,0,0,0,0,0,0,0); signal1(0,1,1,1,1,1,1,1,1); signal1(0,0,1,1,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void UU(){ signal1(1,1,1,1,1,1,1,1,1); signal1(1,0,0,0,0,0,0,1,1); signal1(1,1,1,1,1,1,1,0,1); signal1(1,1,1,1,1,1,1,1,0); signal1(1,1,1,1,1,1,1,1,0); signal1(1,1,1,1,1,1,1,0,1); signal1(1,0,0,0,0,0,0,1,1); signal1(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void VV(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,0,0,0,1,1,1,1,1); signal1(1,1,1,1,1,0,1,1,1); signal1(1,1,1,1,1,1,1,0,1); signal1(1,1,1,1,1,1,1,1,0);

signal1(1,1,1,1,1,1,1,0,1); signal1(1,1,1,1,1,0,1,1,1); signal1(0,0,0,0,1,1,1,1,1); signal1(1,1,1,1,1,1,1,1,1); } void ZZ(){ signal1(1,1,1,1,1,1,1,1,1); signal1(0,1,1,1,1,1,1,0,1); signal1(0,0,1,1,1,1,1,0,1); signal1(0,1,0,1,1,1,1,0,1); signal1(0,1,1,0,1,1,1,0,1); signal1(0,1,1,1,0,1,1,0,1); signal1(0,1,1,1,1,0,0,0,1); signal1(1,1,1,1,1,1,1,1,1); }

void AAA(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,0,0,0,0,0,0,0); signal2(1,0,1,1,1,1,1,1,1); signal2(0,1,1,1,0,1,1,1,1); signal2(0,1,1,1,0,1,1,1,1); signal2(1,0,1,1,0,1,1,1,1); signal2(1,1,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void BBB(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,0,0,0,1); signal2(0,0,0,0,0,1,1,1,0); signal2(0,1,1,1,0,1,1,1,0); signal2(0,1,1,1,0,1,1,1,0); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void CCC(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,0);

signal2(0,1,1,1,1,1,1,1,0); signal2(0,1,1,1,1,1,1,1,0); signal2(0,1,1,1,1,1,1,1,0); signal2(1,0,0,0,0,0,0,0,1); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void DDD(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,0,0,0,0,0,1,1); signal2(1,0,1,1,1,1,1,0,1); signal2(0,1,1,1,1,1,1,1,0); signal2(0,1,1,1,1,1,1,1,0); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void EEE(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,0); signal2(0,1,1,1,0,1,1,1,0); signal2(0,1,1,1,0,1,1,1,0); signal2(0,1,1,1,0,1,1,1,0); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void FFF(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,1); signal2(0,1,1,0,1,1,1,1,1); signal2(0,1,1,0,1,1,1,1,1); signal2(0,1,1,0,1,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void GGG(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,0,1,1,1); signal2(1,0,1,1,1,0,0,0,1); signal2(0,1,1,1,1,0,1,1,0); signal2(0,1,1,1,1,0,1,1,0); signal2(0,1,1,1,1,1,1,1,0); signal2(1,0,0,0,0,0,0,0,1); signal2(1,1,1,1,1,1,1,1,1);

delayMicroseconds(t); } void HHH(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,0,0,1,1,1,1); signal2(1,1,1,0,0,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void III(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,0); signal2(0,0,0,0,0,0,0,0,0); signal2(0,1,1,1,1,1,1,1,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void JJJ(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,0,0,1); signal2(0,1,1,1,1,1,1,1,0); signal2(0,1,1,1,1,1,1,1,0); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void KKK(){//LOW=1 HIGH=0 signal2(1,1,1,1,1,1,1,1,1); signal2(0,0,0,1,1,1,0,0,0); signal2(1,1,1,0,1,0,1,1,1); signal2(1,1,1,1,0,1,1,1,1); signal2(1,1,1,1,0,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void LLL(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,0); signal2(1,1,1,1,1,1,1,1,0); signal2(1,1,1,1,1,1,1,1,0); signal2(1,1,1,1,1,1,1,1,0); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1);

delayMicroseconds(t); } void MMM(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,0,0,0,0,0,0,0,0); signal2(0,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,1); signal2(1,0,0,0,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,1); signal2(1,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void NNN(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,0,1); signal2(1,1,1,1,1,1,0,1,1); signal2(1,1,1,1,1,0,1,1,1); signal2(1,1,1,1,0,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void OOO(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(0,1,1,1,1,1,1,1,0); signal2(0,1,1,1,1,1,1,1,0); signal2(0,1,1,1,1,1,1,1,0); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void PPP(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,0,0,0,0,1,1,1,1); signal2(0,1,1,1,1,0,1,1,1); signal2(0,1,1,1,1,0,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void RRR(){ signal2(1,1,1,1,1,1,1,1,1);

signal2(1,1,1,1,1,1,1,1,0); signal2(1,0,0,0,0,1,1,0,1); signal2(0,1,1,1,1,0,0,1,1); signal2(0,1,1,1,1,0,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void SSS(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void TTT(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,0,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,1,1); signal2(0,0,0,0,0,0,0,0,0); signal2(0,1,1,1,1,1,1,1,1); signal2(0,0,1,1,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void UUU(){ signal2(1,1,1,1,1,1,1,1,1); signal2(1,0,0,0,0,0,0,1,1); signal2(1,1,1,1,1,1,1,0,1); signal2(1,1,1,1,1,1,1,1,0); signal2(1,1,1,1,1,1,1,1,0); signal2(1,1,1,1,1,1,1,0,1); signal2(1,0,0,0,0,0,0,1,1); signal2(1,1,1,1,1,1,1,1,1); delayMicroseconds(t); } void VVV(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,0,0,0,1,1,1,1,1); signal2(1,1,1,1,1,0,1,1,1); signal2(1,1,1,1,1,1,1,0,1); signal2(1,1,1,1,1,1,1,1,0);

signal2(1,1,1,1,1,1,1,0,1); signal2(1,1,1,1,1,0,1,1,1); signal2(0,0,0,0,1,1,1,1,1); signal2(1,1,1,1,1,1,1,1,1); } void ZZZ(){ signal2(1,1,1,1,1,1,1,1,1); signal2(0,1,1,1,1,1,1,0,1); signal2(0,0,1,1,1,1,1,0,1); signal2(0,1,0,1,1,1,1,0,1); signal2(0,1,1,0,1,1,1,0,1); signal2(0,1,1,1,0,1,1,0,1); signal2(0,1,1,1,1,0,0,0,1); signal2(1,1,1,1,1,1,1,1,1); }

void signal(int a,int b,int c,int d,int e,int f,int p,int k,int n){ /*Napomena 1=LOW 0=HIGH*/ if(a==1)digitalWrite(52,LOW); else digitalWrite(52,HIGH); if(b==1)digitalWrite(51,LOW); else digitalWrite(51,HIGH); if(c==1)digitalWrite(46,LOW); else digitalWrite(46,HIGH); if(d==1)digitalWrite(45,LOW); else digitalWrite(45,HIGH); if(e==1)digitalWrite(40,LOW); else digitalWrite(40,HIGH); if(f==1)digitalWrite(39,LOW); else digitalWrite(39,HIGH); if(p==1)digitalWrite(34,LOW); else digitalWrite(34,HIGH); if(k==1)digitalWrite(33,LOW); else digitalWrite(33,HIGH); if(n==1)digitalWrite(28,LOW); else digitalWrite(28,HIGH); delayMicroseconds(t); } void signal1(int a,int b,int c,int d,int e,int f,int p,int k,int n){ /*Napomena 1=LOW 0=HIGH*/ if(a==1)digitalWrite(53,LOW); else digitalWrite(53,HIGH);

if(b==1)digitalWrite(48,LOW); else digitalWrite(48,HIGH); if(c==1)digitalWrite(47,LOW); else digitalWrite(47,HIGH); if(d==1)digitalWrite(42,LOW); else digitalWrite(42,HIGH); if(e==1)digitalWrite(41,LOW); else digitalWrite(41,HIGH); if(f==1)digitalWrite(36,LOW); else digitalWrite(36,HIGH); if(p==1)digitalWrite(35,LOW); else digitalWrite(35,HIGH); if(k==1)digitalWrite(30,LOW); else digitalWrite(30,HIGH); if(n==1)digitalWrite(29,LOW); else digitalWrite(29,HIGH); delayMicroseconds(t); }

void signal2(int a,int b,int c,int d,int e,int f,int p,int k,int n){ /*Napomena 1=LOW 0=HIGH*/ if(a==1)digitalWrite(50,LOW); else digitalWrite(50,HIGH); if(b==1)digitalWrite(49,LOW); else digitalWrite(49,HIGH); if(c==1)digitalWrite(44,LOW); else digitalWrite(44,HIGH); if(d==1)digitalWrite(43,LOW); else digitalWrite(43,HIGH); if(e==1)digitalWrite(38,LOW); else digitalWrite(38,HIGH); if(f==1)digitalWrite(37,LOW); else digitalWrite(37,HIGH); if(p==1)digitalWrite(32,LOW); else digitalWrite(32,HIGH); if(k==1)digitalWrite(31,LOW); else digitalWrite(31,HIGH); if(n==1)digitalWrite(26,LOW); else digitalWrite(26,HIGH); delayMicroseconds(t); }

17) Arduino Fast IR Game with Any Remote Control

COMPONENTS AND SUPPLIES Arduino Nano R3 It also worked with an UNO

Adafruit Standard LCD - 16x2 White on Blue

×

1

×

1

with I2C connection

IR receiver (generic) ×

1

×

11

×

1

Jumper wires (generic)

Any Remote Control

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT I didn't use the IR receiver until this project, so I decided to make the control via remote control. It was also important for me to make the program learn which keys you want to use. So you don not have to figure out what kind of value you need for all the keys you use and put it in the code. You just teach the game once you started it which key ist up, down, left and so on. Well, you have to do this every time you reset the board...

You can see a level 3 gameplay. An 'arrow down' coming from the left. Push the key for 'arrow down' Everytime you hit a wrong key, the symbol went to the other side of the screen or you hit the key while the symbol is behind a fence the score gets less. Otherwise the score goes up.

Left corner shows level, right corner shows Score. Score less then 0 means 'Game Over'

SCHEMATICS I did not find an LCD with I2C board (LCD 1602 + I2C HD44780 Modul). So I just made a shematic. My IR Diode (VS1838B LIRC) is connected like in this sheme, but make shure you make the right connection!! (Data: orange, GND: black, VCC: red). You can use an Arduino Nano or Uno.

CODE #include #include #include

char up = 3; char down = 1; char ok = 2; // Define 3 characters for the LCD Display byte up1[8] = { B00100, B01110, B10101, B00100, B00100, B00100, B00100, B00100 }; byte down1[8] = { B00100, B00100, B00100, B00100, B00100, B10101, B01110, B00100 }; byte ok1[8] = { B01110, B01010, B01110, B10000, B10100, B11000, B10100, B10010 }; int RECV_PIN = 11; // IR Sensor on Pin 11 char* howtoplay[23] = { "> FAST IR GAME 9999) ? 5 : (score > 999) ? 4 : (score > 99) ? 3 : (score > 9) ? 2 : 1; // Draw the scene terrainUpper[TERRAIN_WIDTH] = '\0'; terrainLower[TERRAIN_WIDTH] = '\0'; char temp = terrainUpper[16-digits]; terrainUpper[16-digits] = '\0';

lcd.setCursor(0,0); lcd.print(terrainUpper); terrainUpper[16-digits] = temp; lcd.setCursor(0,1); lcd.print(terrainLower); lcd.setCursor(16 - digits,0); lcd.print(score); terrainUpper[HERO_HORIZONTAL_POSITION] = upperSave; terrainLower[HERO_HORIZONTAL_POSITION] = lowerSave; return collide; } // Handle the button push as an interrupt void buttonPush() { buttonPushed = true; } void setup(){ pinMode(PIN_READWRITE, OUTPUT); digitalWrite(PIN_READWRITE, LOW); pinMode(PIN_CONTRAST, OUTPUT); digitalWrite(PIN_CONTRAST, LOW); pinMode(PIN_BUTTON, INPUT); digitalWrite(PIN_BUTTON, HIGH); pinMode(PIN_AUTOPLAY, OUTPUT); digitalWrite(PIN_AUTOPLAY, HIGH); pinMode(PIN_BUZZER,OUTPUT);//initialize the buzzer pin as an output digitalWrite(PIN_BUZZER, LOW); // Digital pin 2 maps to interrupt 0 attachInterrupt(0/*PIN_BUTTON*/, buttonPush, FALLING); initializeGraphics(); lcd.begin(16, 2); } void loop(){ static byte heroPos = HERO_POSITION_RUN_LOWER_1; static byte newTerrainType = TERRAIN_EMPTY; static byte newTerrainDuration = 1; static bool playing = false; static bool blink = false; static unsigned int distance = 0;

if (!playing) { drawHero((blink) ? HERO_POSITION_OFF : heroPos, terrainUpper, terrainLower, distance >> 3); if (blink) { lcd.setCursor(0,0); lcd.print("Press Start"); } delay(250); blink = !blink; if (buttonPushed) {

initializeGraphics(); heroPos = HERO_POSITION_RUN_LOWER_1; playing = true; buttonPushed = false; distance = 0; } return; } // Shift the terrain to the left advanceTerrain(terrainLower, newTerrainType == TERRAIN_LOWER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); advanceTerrain(terrainUpper, newTerrainType == TERRAIN_UPPER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); // Make new terrain to enter on the right if (--newTerrainDuration == 0) { if (newTerrainType == TERRAIN_EMPTY) { newTerrainType = (random(3) == 0) ? TERRAIN_UPPER_BLOCK : TERRAIN_LOWER_BLOCK; newTerrainDuration = 2 + random(10); } else { newTerrainType = TERRAIN_EMPTY; newTerrainDuration = 10 + random(10); } } if (buttonPushed) { if (heroPos > 3)) { playing = false; // The hero collided with something. Too bad. for (int i = 0; i = HERO_POSITION_JUMP_3 && heroPos = HERO_POSITION_RUN_UPPER_1 && terrainLower[HERO_HORIZONTAL_POSITION] == SPRITE_TERRAIN_EMPTY) { heroPos = HERO_POSITION_JUMP_5; } else if (heroPos == HERO_POSITION_RUN_UPPER_2) { heroPos = HERO_POSITION_RUN_UPPER_1; } else { ++heroPos; } ++distance; digitalWrite(PIN_AUTOPLAY, terrainLower[HERO_HORIZONTAL_POSITION + 2] == SPRITE_TERRAIN_EMPTY ? HIGH : LOW); } delay(100); digitalWrite(PIN_BUZZER,LOW); }

34) Arduino Turn Your RC Car to Bluetooth RV Car

COMPONENTS AND SUPPLIES SparkFun Arduino Pro Mini 328 3.3V/8MHz

Texas Instruments Dual H-Bridge motor drivers L293D

×

1

×

1

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT

Step 1: Getting the right chassis

Part List ProMini L293d module hc-05 Rc car Getting the right chassis To choose chassis is a question about drive mechanism there are many drive mechanism. Lets talk about the two most popular mechanism. Differential Drive What is Differential drive? The term differential means difference between two entities, in the context of robotics it is just the speed difference between two motors.Based on this speed difference, a robot can be moved in any direction on a 2D layout. When two motors are connected to wheels in one line,opposite to each other(Just like a pair of wheels connected to a single shaft) the speed with which each motor rotates determines the direction of motion. When both the wheels rotate at the same speed the difference between the motors is Zero. This makes the robot move forward in a straight

line.The robot can move in reverse direction if the direction of rotation of both the motors are reversed. This will again be in a straight line if the speed difference is zero. Now changing the speed of any one motor will result in movement in a direction away from the straight line. For example, reducing the speed of the right motor will result in a speed difference and hence change in direction.The resultant force is such that the robot turns right. This direction change can be controlled to required angle by further reducing the speed of the motor.Slower is the right motor, sharper is the turn to right. This is exactly the same for Left turn. As a conclusion, Slower right motor, sharper right turn. Slower left motor Sharper left turn. Below are some scenarios which explains working of differential drive mechanism. M1 and M2 are motors which drive wheels on left and right respectively. Steer Type Drive What is Steer type drive ? The car type drive is the most common in real world but not in robot world. It is characterized by a pair of driving wheels and a separate pair of steering wheels The translation and rotation are independent of each other. But translation and rotation are interlinked hence this system faces severe path planning problem. Four wheels are more efficient compared to three or two wheels. The first two of the four wheels can be used to steer and the next two to drive the robot. Balancing a four wheeled robot is never an issue. Most everyday cars we use are four wheeled and the example is enough to prove its existence and capabilities. Disadvantages Of Car Type Drive : The turning mechanism must be accurately controlled. A slight inaccuracy may cause large odometry errors The system is Non – Holonomic hence path planning is extremely difficult as well as inaccurate There are no direct directional actuators So its better to use differential drive due to its simplicity and easy to use.

Step 2: Controlling the motors

To control the motor we need something that something called the

motor driver. What is a Motor Driver? A motor driver is a little current amplifier; the function of motor drivers is to take a low-current control signal and then turn it into a higher-current signal that can drive a motor. There are many motor drivers out of which I am using l293d motor driver module. L293D is a Motor driver integrated circuit which is used to drive DC motors rotating in either direction. It is a 16-pin IC which can control a set of two DC motors simultaneously. The L293D uses 5V for its own power and external power source is needed to drive the motors, which can be up to 36V and draw up to 600mA. The L293D works on the concept of typical H-bridge, a circuit which allows the high voltage to be flown in either direction. In a single L293D IC there are two Hbridge circuits which can rotate two DC motors independently. Pin description of L293d 1Enable pin for Motor 1; active high Enable 1,2 2 Input 1 for Motor 1 Input 1 3 Output 1 for Motor 1 Output 1 4 Ground (0V) Ground 5 Ground (0V) Ground 6 Output 2 for Motor 1 Output 2 7 Input 2 for Motor 1 Input 2 8 Supply voltage for Motors; 9-12V (up to 36V) Vcc 2 9 Enable pin for Motor 2; active high Enable 3,4 10 Input 1 for Motor 1 Input 3 11 Output 1 for Motor 1 Output 3 12 Ground (0V) Ground 13 Ground (0V) Ground 14 Output 2 for Motor 1 Output 4 15 Input2 for Motor 1 Input 4 16 Supply voltage; 5V (up to 36V) Vcc 1

Step 3: About the App

There are many apps to control I made with one .The logic is very simple all the button sends a character when pressed through Bluetooth and the arduino processes it. Character Functions X Null state F Forward Motion B Backward Motion L Turn Left R Turn Right Step 4: Connection all the part

Connections are simple here are the connection as follows The Bluetooth Module Hc-05 Arduino Vcc 5v Gnd Gnd Rx Tx Tx Rx The Motor Driver Motor Driver Arduino pin 2 8 pin 7 7 pin 10 6 pin 4 9 pin 3 and 6 Motor 1 pin 11 and pin 14 Motor 2 pin 1 5v pin 9 5v SCHEMATICS

CODE void setup() { Serial.begin(9600); pinMode(8, OUTPUT); pinMode(7, OUTPUT); pinMode(9, OUTPUT);

pinMode(6, OUTPUT); pinMode(5, OUTPUT); pinMode(4, OUTPUT); digitalWrite(4,LOW); digitalWrite(5,LOW); } // the loop function runs over and over again forever void loop() { var=Serial.read(); if(var=='F') { digitalWrite(6,LOW); digitalWrite(7,HIGH); digitalWrite(8,LOW); digitalWrite(9,HIGH);

} if(var=='H') { digitalWrite(frled1,HIGH); } if(var=='B') { analogWrite(speeden,150); digitalWrite(6,HIGH); digitalWrite(7,LOW); digitalWrite(8,HIGH); digitalWrite(9,LOW); digitalWrite(bcled1,HIGH); }

if(var=='X') {digitalWrite(9,LOW); digitalWrite(8,LOW); digitalWrite(7,LOW); digitalWrite(6,LOW); digitalWrite(frled1,LOW); digitalWrite(bcled1,LOW ); } if(var=='L') {digitalWrite(6,LOW); digitalWrite(7,LOW); digitalWrite(8,HIGH); digitalWrite(9,LOW); } if(var=='R') {digitalWrite(6,HIGH); digitalWrite(7,LOW); digitalWrite(8,LOW); digitalWrite(9,LOW);; } }

35) Arduino Digital Dice

COMPONENTS AND SUPPLIES Breadboard (generic) ×

1

×

1

Jumper wires (generic)

Adafruit Standard LCD - 16x2 White on Blue

×

1

×

1

×

1

×

1

×

1

USB-A to B Cable

Arduino UNO & Genuino UNO

Rotary potentiometer (generic)

SparkFun Pushbutton switch 12mm

ABOUT THIS PROJECT This project was based on the idea that I had become bored of my normal standard game dice. So, to fix my boredom, I decided to use my

Arduino LCD and standard push button (with a breakout board) and I had the Arduino read the state of the signal pin on the button board to high or low (high if button not depressed) (low if not). Depending on the state it would either stay on the main screen or show that the dice are rolling and then print out two random numbers from 1-6 (like a dice). SCHEMATICS

CODE #include long randNumber; int Led = 13; //define LED port int Shock = 2; //define shock port int val;//define digital variable val // initialize the library with the numbers of the interface pins LiquidCrystal lcd(7, 8, 9, 10, 11, 12 ); byte customChar[] = { B00000, B00000, B11111, B11001, B10101, B10011, B11111, B00000 }; void setup() { lcd.begin(16, 2); lcd.createChar(0, customChar); lcd.home(); pinMode(Led, OUTPUT); //define LED as a output port randomSeed(analogRead(0)); pinMode(Shock, INPUT); //define shock sensor as a output port lcd.write(byte( 0)); lcd.print("Digital dice"); lcd.write(byte( 0)); delay(1000); } void loop() { val = digitalRead(Shock); //read the value of the digital interface 3 assigned to val

if (val == LOW) //when the shock sensor have signal do the following { lcd.clear(); lcd.print("Rolling dice..."); delay(4000); lcd.clear(); lcd.setCursor(0, 0); randNumber = random(1,7); lcd.print("Dice 1 = "); lcd.print(randNumber); lcd.setCursor(0, 1); randNumber = random(1,7); lcd.print("Dice 2 = "); lcd.print(randNumber); } delay(150); }

36)Arduino I2S Theremin

COMPONENTS AND SUPPLIES Arduino MKR Zero ×

1

×

1

×

1

×

1

×

1

×

2

Breadboard (generic)

Jumper wires (generic)

Adafruit MAX98357A Speaker: 3W, 4 ohms

RobotGeek Slider

APPS AND ONLINE SERVICES Arduino IDE

Arduino Web Editor

ABOUT THIS PROJECT Arduino I2S library The new Arduino I2S library allows you to send and receive digital audio data on the I2S bus. This example aims to show how to use this library to drive an I2S DAC to reproduce sound computed within the Arduino sketch. For more information about the library and how it works read the library page. I2S Connections The I2S DAC used in this example needs only 3 wires for the I2S bus (plus power supply). Connections for the I2S on the Arduino MKRZero are the following: SD (Serial Data) on pin A6; SCK (Serial Clock) on pin 2; FS (Frame or Word Select) on pin 3; How it works

A theremin has basically two controls: pitch volume In this example these two parameters are changed moving two slide potentiometers, but you can modify it to read them using for example a ping sensor! In this way your theremin will be more realistic! The two potentiometers are wired in a voltage divider fashion, so moving them you will get (from analogRead()) values in the range 0 1023. These values are then mapped to between the minimum and maximum frequency and the minimum and maximum volume. The sound sent on the I2S bus is a simple sine whose frequency and amplitude is changed according to the potentiometers reading.

SCHEMATICS

CODE * This code is based on Adafruit's work https://github.com/adafruit/Adafruit_ZeroI2S/blob/master/examples/tone_generator/tone_generator.ino Make an I2S Theremin using an Arduino MKRZero, an I2S DAC and two slider potentiometers! */ #include const int maxFrequency = 5000; //maximum generated frequency const int minFrequency = 220; //minimum generated frequency const int maxVolume = 100; //max volume of the generated frequency const int minVolume = 0; //min volume of the generated frequency const int sampleRate = 44100; //samplerate of the generated frequency const int wavSize = 256; //buffer size short sine[wavSize]; //buffer in which the sine values are stored const int frequencyPin = A0; //pin connected to the pot who determines the frequency of the signal const int amplitudePin = A1; //pin connected to the pot who determines the amplitude of the signal const int button = 6; //pin connected to the button to put the frequency as output void setup() { Serial.begin(9600); //configue the serial ort // Initialize the I2S transmitter. if (!I2S.begin(I2S_PHILIPS_MODE, sampleRate, 16)) { Serial.println("Failed to initialize I2S!"); while (1); } generateSine(); // fill buffer with sine values pinMode(button, INPUT_PULLUP); //put the button pin in input pullup }

void loop() { if (digitalRead(button) == LOW) { float frequency = map(analogRead(frequencyPin), 0, 1023, minFrequency, maxFrequency); //map frequency int amplitude = map(analogRead(amplitudePin), 0, 1023, minVolume, maxVolume); //map amplitude playWave(frequency, 0.1, amplitude); //play sound //print values on serial Serial.print("Frequency = "); Serial.println(frequency); Serial.print("Amplitude = "); Serial.println(amplitude); } } void generateSine() { for (int i = 0; i < wavSize; ++i) { sine[i] = ushort(float(100) * sin(2.0 * PI * (1.0 / wavSize) * i)); //100 is used to not have small numbers } } void playWave(float frequency, float seconds, int amplitude) { // Play back the provided waveform buffer for the specified // amount of seconds. // First calculate how many samples need to play back to run // for the desired amount of seconds. unsigned int iterations = seconds * sampleRate; // Then calculate the 'speed' at which we move through the wave // buffer based on the frequency of the tone being played. float delta = (frequency * wavSize) / float(sampleRate); // Now loop through all the samples and play them, calculating the // position within the wave buffer for each moment in time. for (unsigned int i = 0; i < iterations; ++i) { short pos = (unsigned int)(i * delta) % wavSize; short sample = amplitude * sine[pos]; // Duplicate the sample so it's sent to both the left and right channel. // It appears the order is right channel, left channel if you want to write // stereo sound. while (I2S.availableForWrite() < 2); I2S.write(sample); I2S.write(sample); } }

37) Voice Control Home Automation System Using Arduino and HC05

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

HC-05 Bluetooth Module

1

×

1

×

1

×

1

×

1

Jumper wires (generic)

Two AC Bulbs(Red,Yellow) Relay (generic) Using 4 Channel Relay

APPS AND ONLINE SERVICES

Arduino IDE

Android IoTBoys (Android App)

ABOUT THIS PROJECT We are showing voice control home automation system to control appliances with own voice command. To accomplish this project using an Android app IoTBoys that is available on google play store. Controlling two AC bulbs (Red, Yellow) using 4 channel relay board.

SCHEMATICS

CODE String voice; int RED = 2; int YELLOW = 3; void RedOn(){ digitalWrite (RED, LOW); } void RedOff(){ digitalWrite (RED, HIGH); } void YellowOn(){ digitalWrite (YELLOW, LOW); } void YellowOff(){ digitalWrite (YELLOW, HIGH); } void allon() { digitalWrite (RED, LOW); digitalWrite (YELLOW, LOW); } void alloff() { digitalWrite (RED, HIGH); digitalWrite (YELLOW, HIGH); } void setup() { Serial.begin(9600); pinMode(RED, OUTPUT); pinMode(YELLOW, OUTPUT); digitalWrite (RED, HIGH);

digitalWrite (YELLOW, HIGH); } void loop() { while(Serial.available()) { delay(10); char c=Serial.read(); if(c=='#') { break; } voice += c; } if (voice.length() > 0) { Serial.println(voice); if (voice == "on" || voice== "all on") { allon() ; } else if (voice == "off" || voice=="all off") { alloff() ; } else if(voice =="red" || voice =="red on"){ RedOn(); } else if(voice =="red off"){ RedOff(); } else if(voice =="yellow" || voice =="yellow on"){ YellowOn(); } else if(voice =="yellow off"){ YellowOff(); }

voice=""; } }

38) Arduino A Geiger Counter Simulator

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

Ultrasonic Sensor - HC-SR04 (Generic)

1

×

1

×

1

Relay Module (Generic) This will be used just to make some noise when the relay switched from on to off and viceversa. Then, you shouldn't use a solid state relay.

APPS AND ONLINE SERVICES

Arduino IDE

Android IoTBoys (Android App)

ABOUT THIS PROJECT Introduction and motivation When teaching about radioactivity, one needs to explain the main features of this phenomenon. Some radioactive samples (i.e., alpha and beta emitters) emit electrically charged particles that, when pass through a Geiger counter, make it react with an internal spark whose noise can be heard like a sort of "click". In order to characterise the radioactive sample, one needs to measure the number of particles emitted per unit time (i.e. the frequency of the "clicks"). Such a number, manifestly, increase while the distance between the radioactive source and the Geiger counter decreases, because the latter intercepts more and more particles as the source gets closer to it. Making experiments in a classroom is the best way to let students fix the lesson in their minds. However, making experiments with radioactive sources in a classroom can be dangerous. Then, why not to simulate them? The basic idea

Of course one can use a "virtual" laboratory, but a real piece of hardware is much more effective. Then, I realised a Geiger counter simulator that works this way: an ultrasonic sensor measure the distance of any obstacle in the vicinity of the simulator; a relay is triggered with a probability that depends on the distance. The "click" is produced by the relay switching from on to off and vice versa. Of course, the simulator turns any obstacle in a "radioactive source". However, a clever positioning of the sensor relative to the obstacle make you control wether the simulator should "click" or not. Building the simulator First of all, assemble the system according to the schematic. Keep the wires long enough such that you can then insert the whole system inside a cardboard tube (I use those around which the kitchen paper is rolled up). Before inserting the system inside make two holes close to one end of the cylinder, such that the speaker and the microphone of the ultrasonic sensor can pass through them (see the picture). Load the sketch into the Arduino memory. The loop() starts obtaining the distance between the sensor and an obstacle (if any). To do that you should trigger the sensor with a positive pulse whose duration is at least 10 us (done by the trigger() function). Upon triggering the sensor, it returns a positive pulse after a time T proportional to the time needed to the ultrasonic pulses to be reflected by the obstacle. In order to suppress the effects of spurious reflections, we average 15 measurements. From the average d we derive the number t=1000/d^2. Given that d ranges from about 2 cm to 400 cm, t ranges from almost 0 to about 250. We can then draw a (pesudo-)random number r uniformly distributed between 0 and 1000 and check if r < t. That happens with a probability of t/1000, ranging from almost 0 to 250/1000=25%. If that happens we switch the relay from on to off or viceversa, based on the last status stored in the appropriate variable. As a result, the relay clicks with a probability that depends on the distance of an obstacle from the sensor. When no objects are in front of

the sensor the system is silent (it may click randomly from time to time, but this behaviour is typical of a Geiger counter because of natural radioactivity, cosmic rays or just noise). Putting something pretending to be radioactive in from of the sensor makes the Geiger simulator react with a clicking frequency increasing when the source gets closer. Using the device To effectively use the device while teaching, you can approach any object to the system taking care not to place it in front of the sensor. The Geiger does not click and the object is then classified as non radioactive. You can then approach another object pretending it is a radioactive source. If you put the object in front of the sensor, the system starts clicking and the frequency of the clicks increases while the distance decreases (that's because a larger number of particles emitted from the source can pass through the detector). It is also possible to turn a non radioactive material into a radioactive one putting it in the vicinity of a radioactive source (activation). So you can put the (pretended) radioactive source close to the non radioactive material for a while, then you move the latter close to the sensor...et voilà...you activated it. In fact my Geiger simulator was proven to be very effective with my class and reactions were enthusiast. Someone also thought that I really made experiments with real radioactive materials.

SCHEMATICS

CODE #define CLIK 8 #define ECHO 2 #define TRIG 3 #define c 340.e-6 // the speed of sound void setup() { pinMode(CLIK, OUTPUT); pinMode(ECHO, INPUT); pinMode(TRIG, OUTPUT); digitalWrite(TRIG, LOW); digitalWrite(CLIK, LOW); } void trigger() { /* trigger the sensor */ digitalWrite(TRIG, HIGH); delayMicroseconds(10); digitalWrite(TRIG, LOW); } float measure() { /* measure the distance between the sensor and the obstacle */ float d = 0.; for (int i = 0; i < 15; i++) { trigger(); unsigned long T = pulseIn(ECHO, HIGH); d += c*T/2.; } return d; } int status = HIGH; // the current status of the relay void loop() { float d = measure(); unsigned long trigger = 1000./(d*d); unsigned long r = random(1000); if (r < trigger) { digitalWrite(CLIK, status); if (status == HIGH) { status = LOW; } else { status = HIGH; }

} }

39) Arduino Based Collision Detection Warning System

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

1

ultrasonic sensor HR SC-04

LED (generic) ×

2

×

1

×

2

Buzzer

Resistor 10k ohm

ABOUT THIS PROJECT This is an Arduino-based collision detection warning system. This kind of system is the fastest growing safety feature in automotive industries. Such a system enables vehicles to identify the chances of collision and give visual and audio warning to driver, so that the driver can take necessary action to avoid collision. This project idea is based on an Arduino controller and the whole project will give you very good understanding of how this system works. The step-by-step method is explained so that you can make this system. The hardware connection, pin information and Arduino program is explained clearly.

Step 1: Please gather the following items Computer: This is required to write program and flash program to the controller. Also, you need to install Arduino IDE which is available free on the Arduino website download section.

Controller: I used Arduino micro-controller. This you can get from an online seller like Amazon, etc. Sensor: I used HR SC-04 ultrasonic sensor. Piezo Buzzer: I used Piezo buzzer to make the audio warning. LED: There are two colors of LED I used - red and blue. Wires: Jumper wires are required to make hardware connections. You need to use all types of jumper wires like male-male, female-female and female-male.

Step 2: Connect all hardware The hardware you gather in first step, now connect all of them to the controller through wires. Sensor to controller pin information The sensor has four pins: VCC, Trig, Echo, and GND. Connect: VCC pin to 5V on controller

GND pin to GND on controller Trig pin to pin-7 on controller Echo pin to pin-4 on controller Piezo Buzzer to controller pin information Piezo buzzer has two pins: Connect one pin to pin-10 on controller Connect another pin to GND on controller Red LED to controller pin information The red LED has two pins: Connect one pin to pin-2 on controller Connect another pin to GND on controller Blue LED to controller pin information The blue LED has two pins: Connect one pin to pin-13 on controller Connect another pin to GND on controller Controller to Computer connection information You have a USB data cable that you get with buying the Arduino. With this data cable, you connect the computer to the Arduino board. Now launch Arduino IDE. After connecting the computer, you must select the board and port from the menu. Please see the attached screen shot for the help.

Step 3: Write the program In the previous step, we defined pin information for the hardware. Now, that info we'll use to write program instructions. Launch Arduino IDE and

try to write the program by yourself. Otherwise you can directly use my program or download the .ino format file attached. While copying this code, you have to be careful because some characters used in the program cannot be paste while writing this on particular medium. Better to download .ino format file. ////Collision Warning System//// //// Year 2017 //// //// Vijendra Kumar//// const int trigPin = 7; const int echoPin = 4; int buzz = 10; long duration; int distance; // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin 13 as an output. pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(13, OUTPUT); pinMode(2, OUTPUT); Serial.begin(9600); } // the loop function runs over and over again forever void loop() { // Clears the trigPin digitalWrite(trigPin, LOW); delayMicroseconds(2);

// Sets the trigPin on HIGH state for 10 micro seconds digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Reads the echoPin, returns the sound wave travel time in microseconds duration = pulseIn(echoPin, HIGH); // Calculating the distance distance= duration*0.034/2; // Prints the distance on the Serial Monitor if(distance = 20) { digitalWrite(13, HIGH); // digitalWrite(13, LOW); // turn the LED on (HIGH is the voltage level) } else { digitalWrite(13, LOW); // turn the LED off by making the voltage LOW // wait for a second } if(distance (kivantHomerseklet+homDiff)) && relayPin0==LOW) { digitalWrite(relayPin0, HIGH); } if ((metro0.check() == 1) && (tempCaverage < (kivantHomerseklet-homDiff))) { // check if the metro has passed its interval . if (state0==HIGH) { state0=LOW; metro0.interval(idoZar); //Zarasi ido } else { state0=HIGH; metro0.interval(varZar); // if the pin is LOW, set the interval to 1 second. } digitalWrite(relayPin0,state0); } if ((metro1.check() == 1) && (tempCaverage > (kivantHomerseklet+homDiff))) { // check if the metro has passed its interval . if (state1==HIGH) { state1=LOW; metro1.interval(idoNyit); // if the pin is HIGH, set the interval to 0.25 seconds. } else { state1=HIGH; metro1.interval(varNyit); // if the pin is LOW, set the interval to 1 second. } digitalWrite(relayPin1,state1); }

sensors.requestTemperatures(); // Homerotol beolvassunk a homersekletet

}

53) Arduino CNC Flatbed Pen Plotter

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

USB A-B Cable

5V 1.2A AC-to-DC Adapter

×

1

×

1

Should be plugged via 2.1mm center-positive plug to the Arduino's power jack. Stepper Motor 28BYJ-48 - 5V

×

1

×

4

×

4

×

4

×

1

×

1

20cm Male-to-Male Jumper Wire Cable 2.54mm

×

20

20cm Male-to-Female Jumper Wire Cable 2.54mm

×

40

Driver PCB based on ULN2003A It is useful for driving unipolar stepper motors. Works like digital amplifier. M6 Coupling Nut 10 mm Long Needed to fix rod with motor's shaft. M6 Threaded Rod 1 meter is just fine. Universal breadboard SYB-46 Solderless technologies!

NECESSARY TOOLS AND MACHINES Vernier Caliper Needed for precise and convenient meter measurement. Electric Drill As alternative, electric screwdriver comes handy, but it's not recommended. M5 Metal Drill Bit Needed for making holes in movable weights for threading. M6 Metalworking Drill Tap Needed for threading in these weights. M2 Metal Drill Bit Needed for making holes in long nuts. M3 Metalworking Drill Tap Needed for threading in these nuts. Angle Grinder Needed for cutting and chamfering of threaded rod with use of cut-off wheel. Cut-off Wheel Mechanical Pencil 0.5 mm Or use any other pen (preferably with very liquid ink). Solid (metallic or wooden) flat weight with size of 1" approx. https://www.hackster.io/VINTproYKT/cnc-

flatbed-pen-plotter-1780c9/logs/2

APPS AND ONLINE SERVICES Arduino IDE

AccelStepper library for Arduino This library provides an object-oriented interface for 2, 3 or 4 pin stepper motors and motor drivers. Inkscape Extensible vector graphics editor with Python 2.7.* included. Needed to write our own CAM extension. Gcodetools plug-in for Inkscape Needed to convert vector image to good Gcode. ABOUT THIS PROJECT I've decided to construct flatbed pen plotter for my graduation project in October 2016. Time to think was enough. The idea behind this creation is to print precise A4 drawings with nearly any pen: pencil, ball pen, marker pen, etc. Flatbed plotter needs linear actuators in all 3 axes. First of all, I was thinking about belts. But they spinned out to be really expensive for my project. That’s why I thought that nothing more quicker to construct and accurate to move than the lead screw could help emphasize economic efficiency of installation. It's because searching for belts and cogs in our region is bit more challenging. Since that time I understood which motors and drivers would be more expedient to acquire - 28BYJ-48 and PCB based on ULN2003A. Came

to the conclusion that I very have to buy and test them. I learned that we also need to beware of untrusted manufacturers. Power supply I don’t too much prefer switching power supply (as from PC) because of its sizes, weight and electromagnetic influence. It is good for powering big creations, but not necessary for my small CNC plotter. Summarizing maximum currents for motors, use of portable 1 A power supply is enough, so I also can easily connect it to Arduino’s DC jack. Neat! Why I chose 28BYJ-48 - 5V? This unipolar stepper motor easily integrates into CNC machine - 5V is just fine with usual power supply. 28BYJ-48 consists of four coils, that should be controlled in order AAB-B-BC-C-CD-D-DA or vice versa for counterclockwise rotation. This movement mode is called half-step, because shaft is magnetized by two phase after one, by one after two and so on. Some research helped to find out maximum current for coils at fast speed - 200 mA, at stop - 250 mA. Let’s suppose that all four motors are stopped at the same time - 4 × 250 mA = 1 A. Usual power supply comes handy as ever. You can also stop powering motors when you don’t move them. Some 28BYJ-48 motors have crappy reductor, because, you know these cogs. 5 minutes of rotating showed that I have actually good reductor - number of steps per revolution on constant speed make exactly 360°. Maybe more hours of work will show real face of this monster. Why I chose driver PCB based on ULN2003A? First of all, what about hacking from unipolar to bipolar 28BYJ-48, as some people advise, by cutting middle copper connection leading from red wire under plastic cap? It's not the bad idea at all. You will get decent speedup! But it's out of motor's purpose - by the end, min. 3 Hbridge ICs (like the L293D or SN754410NE) will be required. There's also modern A4988 driver with H-bridge for microstepping.

The above boards are not as cheap as chips, because they have complicated switching systems used for driving 4-wire bipolar motors. So, I avoided these tasks and just chose to keep all "as is" and brought PCBs based on ULN2003A. They cost me $0.88/each. But you might chose H-bridges and that’ll be cool. Testing motors At the moment, I have run my motors in 2 directions simultaneously. Every driver PCB converts 4 digital input signals to high-voltage highcurrent output for motor's coils. To control all 3 axes we use 12 digital pins on the controller. Interesting that Arduino Uno has 14 pins in total but 2 of them are connected for serial communication, so we can occupy exactly 12. For axis X we need to synchronously move columns in the point where Y starts and in the point where it ends to compensate the pressure. So there are 2 stepper motors for axis X, each of which has separated driver board. These PCBs have same input signals (from digital pins 2, 3, 4, 5). That's where breadboard can help make parallel connection. Universal breadboard also has a big deal for connections to ground and external voltage. Each of Y and Z axes require only one stepper motor. Y uses digital pins 6, 7, 8, 9, Z - 10, 11, 12, 13. All digital sequences are generated by AccelStepper library. This one is pretty straight-forward in controlling any stepper motors. And one of the best features there is that it can generate signals for multiple motors at one time. Installing lead screws I think about using long nut as threaded bushing. Shaft of the motor has radius of 5 mm. It can get in M6 threaded hole and be fixed by two tiny (M3) screws by its chords. So be ready to make these threaded holes in the nut. Now when nut is fixed on the shaft, we spin M6 threaded rod in it. But here I must stop, because we need to consider some of the preparatory operations, such as positioning a weight (that is being moved along axis), making railway and another fasteners on the base -

one for motor, other for end support.

SCHEMATICS

CODE #include #include #define MOTORS_MAXSPEED 1500 #define MOTORS_ACCELERATION 100 #define MOTORS_STEPS_PER_REVOLUTION 4096 // 28BYJ-48 in half-step mode AccelStepper motorX(AccelStepper::HALF4WIRE, 2, 3, 4, 5); AccelStepper motorY(AccelStepper::HALF4WIRE, 6, 7, 8, 9); AccelStepper motorZ(AccelStepper::HALF4WIRE, 10, 11, 12, 13); MultiStepper motors;

short motors_dir = 1; int motors_avgSpeed = MOTORS_MAXSPEED;// Average speed String input = ""; void doCommand(String command, String param) {// Serial commands hub if (command == "go") { long steps = param.toInt(); if (steps == 0) steps = MOTORS_STEPS_PER_REVOLUTION;// Make full revolution by default _go(steps); } else if (command == "stop") _stop(); else if (command == "dir") _dir(); else if (command == "speed") { float speed = param.toInt(); if (speed == 0) speed = MOTORS_MAXSPEED;// Average speed equals maximum speed by default _speed(speed); } } void setup() { Serial.begin(115200);// Maximum baud rate for Arduino Uno Serial.println("Запуск"); input.reserve(128); motorX.setMaxSpeed(MOTORS_MAXSPEED); motorY.setMaxSpeed(MOTORS_MAXSPEED); motorZ.setMaxSpeed(MOTORS_MAXSPEED); motorX.setAcceleration(MOTORS_ACCELERATION); motorY.setAcceleration(MOTORS_ACCELERATION); motorZ.setAcceleration(MOTORS_ACCELERATION); motors.addStepper(motorX); motors.addStepper(motorY); motors.addStepper(motorZ); } void loop() { while (Serial.available()) { input = Serial.readStringUntil('\n'); input.trim(); int input_sp = input.indexOf(' ');// Checking for space character in input string String input_command = input;

String input_param; if (input_sp > 0) { input_command = input.substring(0, input_sp); input_param = input.substring(input_sp + 1); input_param.trim(); } doCommand(input_command, input_param); input = ""; } measureSteps(); motors.run(); } void _go(long increment) { if (motorX.speed() == 0) { motorX.setSpeed(motors_avgSpeed); motorY.setSpeed(motors_avgSpeed); motorZ.setSpeed(motors_avgSpeed); motors.moveTo(motorX.currentPosition() + motors_dir * increment); Serial.print("Move to "); Serial.print(motorX.targetPosition()); Serial.print(" (rotate by "); Serial.print((float)increment / (float)MOTORS_STEPS_PER_REVOLUTION * 360); Serial.print("° "); if (motors_dir < 0) Serial.print("counter"); Serial.print("clockwise"); Serial.println(")"); } } void _stop() { motors.moveTo(motorX.currentPosition()); motorX.setSpeed(0); motorY.setSpeed(0); motorZ.setSpeed(0); motorX.stop(); motorY.stop(); motorZ.stop(); Serial.println("Stopped"); } void _dir() { motors_dir = -motors_dir; if (motors_dir > 0) Serial.println("CW");

else Serial.println("CCW"); } void _speed(float speed) { motors_avgSpeed = speed; Serial.print("Average speed changed to "); Serial.println(speed); } void measureSteps() { if (motorX.speed() != 0) { Serial.print("Position: "); Serial.print(motorX.currentPosition()); Serial.print(" | Speed: "); Serial.print(motorX.speed()); Serial.println(" steps/s"); } }

54) Arduino Bracelet Dodges Obstacles

COMPONENTS AND SUPPLIES Arduino Nano R3 ×

Ultrasonic Sensor - HC-SR04 (Generic)

1

×

1

×

1

×

1

×

1

Recycled vibrator motor of cell phone

Recycled cables

5v Rechargable battery of 2000mAh.

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

Fabrics and glue for the lining.

ABOUT THIS PROJECT This project is about a bracelet that can help anyone to perceive an obstacle through a small vibration. In my house I had some components that I used for this project, and I did not know what to do with them, so I thought about how those components can help someone or how they could improve something and after a while of thinking about what to do with them. I realized that it was a good idea to make a bracelet that identifies an obstacle, for people who can not perceive them. Then I searched the Internet for a bit of this, and I seen many people who did similar projects, with the same goal, and I thought it was great to do it with a different and low cost perspective. It works in a very simple way. The ultrasonic sensor HC-SR04 connected to the arduino emits a wave, this wave when hitting an obstacle returns and receives the sensor, by means of this we can obtain the distance to which this is an obstacle of the sensor and we program it so that in a range from one certain distance, the vibrator motor will turn on and vibrate.

SCHEMATICS

CODE #define echo 8 #define trig 7 long duration,distance; void setup() { Serial.begin(9600); pinMode(echo,INPUT); pinMode(trig,OUTPUT); pinMode(5,OUTPUT); } void loop() {

digitalWrite(trig,LOW); delayMicroseconds(2); digitalWrite(trig,HIGH); delayMicroseconds(10); digitalWrite(trig,LOW); duration=pulseIn(echo,HIGH); distance=(duration/(2*29)); if(distance>=500 || distance 0) { if (receiveMessageFromPLM() == 0) // message received and compliant with message type definition { Serial.println(); if (inByte[1] == 0x50 && ( (inByte[8] & 0b11100000) == 192) && inByte[9] != 6 ) // we do not support all message types currently, just group broadcast messages { displayInsteonGroupBroadcast(); routeGroupBroadcastMessageToBroker(); Serial.println(); } else { Serial.println(F("Message type not currently supported.")); // See http://www.madreporite.com/insteon/receiving.html Serial.println(); } }; }; // Part 2 : deal with messages originating from MQTT Broker. Those messages are waiting in a local queue while (!cmdQueue.isEmpty ()) { if (parseMessage() == 0) { sendMessageToInsteonDevice(); }; } // Part 3 : report device status to MQTT broker if (mqttIntervalCnt == 0) { Serial.println(F("Reporting gateway status to MQTT Broker...")); routeGatewayStatusMessageToBroker(); mqttIntervalCnt = mqttInterval; Serial.println(); } else

{ mqttIntervalCnt = mqttIntervalCnt - 1; } // Take some rest delay(mainLoopDelay / 2 ); client.loop(); delay(mainLoopDelay / 2); } // Parse a message stored in the local queue int parseMessage() { byte b; int hex_digit_to_read = 2; bool reading_hex = true; byte hex = 0; for(int j=0;j 0) { hex = (hex 0) { if (currentIndex == 0) { Serial.print(F("### New message entering : ")); } currentByte = InsteonSerial.read(); inByte[currentIndex] = currentByte; displayRawData(currentByte); if (currentIndex == 0 && currentByte != startByte) // a new message should always start with the specified start byte { // displayError2(currentByte); return 2; }; if (currentIndex > 11) // message looks longer than expected { return 4; }; if (currentIndex == 10) // message has been received as expected { return 0; // full message received }; currentIndex = currentIndex + 1; // just keep going with parsing }; }; } // Route a command issued by MQTT Broker to Insteon devices void routeGroupBroacastToInsteon() { // displayInsteonOutgoingGroupBroadcast(); for (int i=0;i 0) { Serial.println("Email send ok"); return true; } else { Serial.println("Email send failed"); return false; } }

65) Arduino 4 Digit 7 Segment Counter with Lipo Backup

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

4

General Purpose Transistor NPN I used 2N3904

Resistor 100 ohm ×

7

×

4

×

1

×

1

×

1

×

1

Resistor 10k ohm

One Channel Relay Module Board Shield Relay Adafruit 4 Digit 7 Segment LED Display, 1.2" Yellow, Common Cathode Just a standard relay from Amazon\Ebay, +5V signal with open connection when there is no signal Adafruit Powerboost 500C Battery, 3.7 V LiPo Battery 18650, 3000mAH

ABOUT THIS PROJECT I needed a counter at work and currently have a habit of making things with bright LEDs. So I came up with this. It uses a large 4-digit 7-segment display, an Adafruit PowerBoost 500C for LiPo battery backup and an Arduino Uno. A relay turns off the display when on battery, there is an option to override this (using black button). The PCB is just a prototype board, I dont have time for etching, it's housed in a perspex case. The controls are to increment the count by +1, +10 and +100, decrement by -1, reset to 0, turn of the display and LEDs to power save when on battery and turn off the unit.

SCHEMATICS

CODE #define button A0 // +1 #define button_minus A1 // -1 #define button_10 A2 // +10 #define button_100 A3 // +100 #define button_reset A4 // reset // common pins of the four digits definitions #define Dig1 2 #define Dig2 3 #define Dig3 4 #define Dig4 5 // segment pin definitions #define SegA 6 #define SegB 7 #define SegC 8 #define SegD 9 #define SegE 10 #define SegF 11 #define SegG 12 // A=10 : // variable declarations byte current_digit; int count = 0; void setup() { pinMode(button, INPUT_PULLUP); pinMode(button_minus, INPUT_PULLUP); pinMode(button_10, INPUT_PULLUP); pinMode(button_100, INPUT_PULLUP); pinMode(button_reset, INPUT_PULLUP); pinMode(SegA, OUTPUT); pinMode(SegB, OUTPUT); pinMode(SegC, OUTPUT); pinMode(SegD, OUTPUT); pinMode(SegE, OUTPUT); pinMode(SegF, OUTPUT); pinMode(SegG, OUTPUT); pinMode(Dig1, OUTPUT); pinMode(Dig2, OUTPUT);

pinMode(Dig3, OUTPUT); pinMode(Dig4, OUTPUT); disp_off(); // turn off the display // Timer1 module overflow interrupt configuration TCCR1A = 0; TCCR1B = 1; // enable Timer1 with prescaler = 1 ( 16 ticks each 1 µs) TCNT1 = 0; // set Timer1 preload value to 0 (reset) TIMSK1 = 1; // enable Timer1 overflow interrupt } ISR(TIMER1_OVF_vect) // Timer1 interrupt service routine (ISR) { disp_off(); // turn off the display switch (current_digit) { case 1: if (count >= 1000) { disp(count / 1000); // prepare to display digit 1 (most left) digitalWrite(Dig1, HIGH); // turn on digit 1 } break; case 2: if (count >= 100) { disp( (count / 100) % 10); // prepare to display digit 2 digitalWrite(Dig2, HIGH); // turn on digit 2 } break; case 3: if (count >= 10) { disp( (count / 10) % 10); // prepare to display digit 3 digitalWrite(Dig3, HIGH); // turn on digit 3 } break; case 4: disp(count % 10); // prepare to display digit 4 (most right) digitalWrite(Dig4, HIGH); // turn on digit 4

} current_digit = (current_digit % 4) + 1; } // main loop void loop() { if(digitalRead(button) == 0) { count++; // increment 'count' by 1 if(count > 9999) count = 0; delay(200); // wait 200 milliseconds } else if(digitalRead(button_minus) == 0) { count--; // decrement 'count' by 1 if(count < 0) count = 9999; delay(200); // wait 200 milliseconds } else if(digitalRead(button_10) == 0) { count=count+10; // increment by 10 if(count > 9999) count = 0; delay(200); // wait 200 milliseconds } else if(digitalRead(button_100) == 0) { count=count+100; // increment by 100 if(count > 9999) count = 0; delay(200); // wait 200 milliseconds } else if(digitalRead(button_reset) == 0) { count=0; // reset delay(200); // wait 200 milliseconds } } void disp(byte number) { switch (number)

{ case 0: // print 0 digitalWrite(SegA, HIGH); digitalWrite(SegB, HIGH); digitalWrite(SegC, HIGH); digitalWrite(SegD, HIGH); digitalWrite(SegE, HIGH); digitalWrite(SegF, HIGH); digitalWrite(SegG, LOW); break; case 1: // print 1 digitalWrite(SegA, LOW); digitalWrite(SegB, HIGH); digitalWrite(SegC, HIGH); digitalWrite(SegD, LOW); digitalWrite(SegE, LOW); digitalWrite(SegF, LOW); digitalWrite(SegG, LOW); break; case 2: // print 2 digitalWrite(SegA, HIGH); digitalWrite(SegB, HIGH); digitalWrite(SegC, LOW); digitalWrite(SegD, HIGH); digitalWrite(SegE, HIGH); digitalWrite(SegF, LOW); digitalWrite(SegG, HIGH); break; case 3: // print 3 digitalWrite(SegA, HIGH); digitalWrite(SegB, HIGH); digitalWrite(SegC, HIGH); digitalWrite(SegD, HIGH); digitalWrite(SegE, LOW); digitalWrite(SegF, LOW); digitalWrite(SegG, HIGH); break; case 4: // print 4 digitalWrite(SegA, LOW); digitalWrite(SegB, HIGH); digitalWrite(SegC, HIGH); digitalWrite(SegD, LOW);

digitalWrite(SegE, LOW); digitalWrite(SegF, HIGH); digitalWrite(SegG, HIGH); break; case 5: // print 5 digitalWrite(SegA, HIGH); digitalWrite(SegB, LOW); digitalWrite(SegC, HIGH); digitalWrite(SegD, HIGH); digitalWrite(SegE, LOW); digitalWrite(SegF, HIGH); digitalWrite(SegG, HIGH); break; case 6: // print 6 digitalWrite(SegA, HIGH); digitalWrite(SegB, LOW); digitalWrite(SegC, HIGH); digitalWrite(SegD, HIGH); digitalWrite(SegE, HIGH); digitalWrite(SegF, HIGH); digitalWrite(SegG, HIGH); break; case 7: // print 7 digitalWrite(SegA, HIGH); digitalWrite(SegB, HIGH); digitalWrite(SegC, HIGH); digitalWrite(SegD, LOW); digitalWrite(SegE, LOW); digitalWrite(SegF, LOW); digitalWrite(SegG, LOW); break; case 8: // print 8 digitalWrite(SegA, HIGH); digitalWrite(SegB, HIGH); digitalWrite(SegC, HIGH); digitalWrite(SegD, HIGH); digitalWrite(SegE, HIGH); digitalWrite(SegF, HIGH); digitalWrite(SegG, HIGH); break; case 9: // print 9

digitalWrite(SegA, HIGH); digitalWrite(SegB, HIGH); digitalWrite(SegC, HIGH); digitalWrite(SegD, HIGH); digitalWrite(SegE, LOW); digitalWrite(SegF, HIGH); digitalWrite(SegG, HIGH); } } void disp_off() { digitalWrite(Dig1, LOW); digitalWrite(Dig2, LOW); digitalWrite(Dig3, LOW); digitalWrite(Dig4, LOW); } // end of code.

66) Arduino Wireless Weather Station

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

×

1

M1201 step down converter DCDC 3-40V to 1.25-35V

×

1

Mini-360 step down converter DCDC 4.75V-23V to 1V-17V

×

1

×

1

×

1

×

1

×

1

×

1

DHT11 Temperature & Humidity Sensor (4 pins)

Carbon Monoxide (CO) Sensor MQ-7 Espressif ESP8266 ESP-12E

SparkFun Logic Level Converter Bi-Directional

5V Low Level Trigger 1 Channel Relay Module SparkFun Pushbutton switch 12mm

×

1

×

1

×

6

×

1

×

1

×

2

×

3

×

1

Basic On/Off DC Switch LED (generic)

Buzzer

USB-A to Micro-USB Cable

1N4007 – High Voltage, High Current Rated Diode

Resistor 10k ohm

Jumper wires (generic)

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

Hot glue gun (generic)

Electric file Multimeter

APPS AND ONLINE SERVICES Arduino IDE

ThingSpeak API

ABOUT THIS PROJECT This project started off as a final assessment homework for an university course I've followed this year, but proved out to be a really fun and practical way of learning new and interesting things about wireless communication and microcontrollers in general. The main idea: The core of this project is an Arduino Uno developing board which gathers data from two sensors: DHT 11 - which is used for measuring temperature and humidity levels MQ-7 - which is used for measuring the CO level in the air (ppm) The data received from the sensors is then sent to www.thingspeak.com by using an ESP8266 12-E Wireless Module. The components and their role:

M1201 step down buck converter (#2) This component is needed to step down the voltage from 5V to 1.4V. The 1.4V are then used to power up the MQ-7 gas sensor for a period of 90s, the so called "reading period". (check MQ-7 datasheet for more info on the operation principle) Note: The one that I had couldn't go down to 1.4V (although it should have) so I've used 2 more diodes to lower the voltage (check the schematics) Mini-360 step down buck converter (#3) This component is needed to step down the voltage from 5V to 3.3V. You can as well see it as the main 3.3V power supply in the system. The 3.3V are used to power up the ESP8266 12-E Wi-Fi module, as well as the low side of the logic level shifter. The ESP8266 12-E is a Wi-Fi module which is powered at 3.3V, NOT 5V. Powering it at 5V will permanently damage the module! The ESP8266 draws more than 200mA of current while operating and sending values to the web server. Powering it from Arduino's 3.3V power pin would be a big mistake as Arduino cannot provide that much current, thus making the Wi-Fi module unstable. SRD-05VDC-SL-C 5V 1 Channel Relay Module(#8) This relay is directly connected on the powering line of the MQ-7 CO gas sensor and has the role of cycling between 1.4V for 90S and 5V for 60s. Why so? Well according to the MQ-7 datasheet you have to heat up the sensor for 90s@5V. Only after the heating cycle you can read the sensor values for the next [email protected]. Note: See the MQ-7 datasheet for mor info on this Logic level shifter 5V - 3.3V (#7) Since the Arduino Uno runs at 5V and the ESP8266 12-E runs at 3.3V the logic levels are quite different between the two components. Thus, when trying to "speak" with the ESP8266 by using the RX,TX (serial communication) ports on the Arduino Uno we need a logic level shifter to do so. This component does exactly what we need: shifts the logic levels from 5V to 3.3V. Check the image (fig. 1) bellow for a visual representation of the

different logic levels. Same thing could also be done way cheaper by directly connecting the RX line between the two components, while using a voltage divider on the TX line of the Arduino Uno. For more info on this check the following link: http://jamesreubenknowles.com/level-shifting-stragetyexperments-1741

fig. 1 Wi-Fi ESP8266 E-12 Wi-Fi module (#6) I guess it's pretty obvious what this part is used for and that's connecting to a local Wi-Fi network (preconfigured in the source code) and sending the sensor data to www.thingspeak.com

On/Off Switch (#10) It seems that one cannot upload a new source code file on the Arduino Uno while having the TX pin connected to another component. If you try to do so you would get a lot of errors in Arduino IDE. While uploading a new sketch the TX pin should be "floating". To do so, I've used a on/off switch to disconnect the TX line from the ESP8266 whenever I want to upload an new code on the board. (check schematics down bellow) MQ-7 Gas Sensor (#5) Used for reading the CO level in the air. The value provided is measured in ppm. As stated earlier check the datasheet to see the working principle. The sensor needs to be powered for 90s@5v, time during which no reading is done, and [email protected], time which represents the reading period. Check the datasheet for info on calibrating the sensor. Reset button (#9) Since the hole wiring will be hidden inside a box a the end of this project, with the Arduino Uno stuck with hot glue at the bottom of box, uploading a new sketch on the board it would pose quite a problem when it comes to physically reseting the board without opening the box. To solve this issue we would need an external reset button. That's exactly what this big red button does. It resets the board. The LED's (#9) 11 - general error indicator (for debugging the error we would need to connect the board to a pc and check the Serial Monitor Interface in Arduino IDE for the error message) 12 - signals the presence/absence of the ESP8266 in the current system 13 - signals if ESP8266 is connected/not connected to the local network 14 - signals sending sensor data tot thingspeak.com 15 - blinks whenever the MQ-7 is heating 16 - blinks whenever Arduino Uno reads data from sensors The Buzzer Whenever the CO level read from the MQ-7 gas sensor exceeds a certain value hardcoded in the code, an alarm will be triggered by using the

buzzer. Software requirements: In order to see the value of sensor data, we will need a private channel on thingspeak.com. We will also need Arduino IDE to write/upload the code for Arduino Uno. List of software requirements: Private channel on Thingspeak.com and Arduino IDE (Preferably latest version). In order for the sketch to work we will also need the DHT11 library which you can download in the attachment section down bellow. For a step by step tutorial on how to add this library to Now lets create a private channel on thingspeak.com Creating private channel on Thingspeak.com To make a private channel on thingspeak.com follow these steps: Open your web browser and go to thingspeak.com and click on 'Sign Up' tab in right top corner, (Image no.1) Fill in the details and click on 'Create account', (Image no.2) Now click on 'New Channel' tab, (Image no.3) Again fill in details for channel and enable 4 fields (as we will be sending 4 sensor values), scroll down and click on 'Save Channel' tab, (Image no.4/5) On this page click on 'API Keys' tab and note down your 'Write API Key'.

That's all folks, now you have your private ThingSpeak channel. Now lets put all electronics component together. The Code The code for Portable weather station is quite simple. I have commented code properly for ease of portability. Before you burn the code take care of following things. Make sure that all libraries are installed, Replace hyphens (--------) with SSID of your access point (wifi router) in line 14 of the code, Replace hyphens (--------) with PASSWORD of your wifi network in line 15 of the code, Replace hyphens (--------) with your ThingSpeak's private channel write API key in line 17 and While uploading the code to the Arduino make sure that the on/off switch on the TX line is set to "off" so that you can upload the code Now that we have our hardware and software in place, only thing remaining is packaging.

The logic If you find the code pretty difficult to understand take a look on the logic diagram down bellow:

Logical Diagram

Blinking order Packaging and enclosing the system Down bellow you are going to find some useful photos taken while I was preparing the enclosure for the system. Make sure you have the tools required to make a box like the one bellow (elecrtic file, soldering iron, hot glue gun...)

As you can see in the third image above I've used some generic "mother" type pins soldered together for providing power/ground to the components of the system. I've then hot glue the piece to the side panel of the box, inside of it. Results You can check the results of this project by clicking on the following link which should redirect you to the public view of my thingspeak channel: https://thingspeak.com/channels/152176

Plotted data Problems encountered during development Sometimes some parts of the system went unresponsive due to poor contact on the breadboard. If the ESP8266 becomes unresponsive out of a sudden, first thing I would suggest doing would be to check the connections once again If you see a lot of garbage in the Serial Monitor console make sure the baud rate in the console is set accordingly with the ESP8266 settings. For more info on changing the baud rate of the Serial Montior console check the following link: https://learn.adafruit.com/adafruit-arduinolesson-5-the-serial-monitor/other-things-to-do For more info on changing the baud rate setting of the ESP8266 check the following link: http://www.esp8266.com/viewtopic.php?f=13&t=718 Make sure you calibrate the MQ-7 sensor correctly as if not you would receive some big measurement errors Future projects tips DHT11 isn't quite precise, in the sense that it can give random errors. A DHT22 sensor would prove much more accurate, but it is also a little

bit more expensive than the DHT11 ESP8266 proved to be a little bit unstable during the development phase. A ESP32 or a NodeMCU board might be better for a future project Some random photos taken during developing stage

SCHEMATICS

CODE #include #include "DHT.h" //-----ESP8266 macros--------#define SSID "------"//your network name #define PASS "------"//your network password #define IP "184.106.153.149" // thingspeak.com #define Baud_Rate 9600 //Another common value is 115200 #define GREEN_LED 3 //optional LED's for debugging #define RED_LED 4 //optional LED's for debugging #define YELLOW_LED 5 //optional LED's for debugging #define ESP_FOUND_LED 6 //optional LED's for debugging #define DELAY_TIME 3000 //time in ms between posting data to ThingSpeak //Can use a post also String GET = "GET /update?key=------"; //String FIELD1 = "&field1="; String FIELD2 = "&field2="; String FIELD3 = "&field3="; bool updated; //----Relay/MQ-7 macros

#define RELAY 8 #define MQ7_ANALOG_IN_PIN 0 #define HEATING_LED 9 #define READING_LED 10 #define BUZZER 11 #define MQ7_HEATER_5_V_TIME_MILLIS 60000 #define MQ7_HEATER_1_4_V_TIME_MILLIS 90000 #define GAS_LEVEL_READING_PERIOD_MILLIS 1000 unsigned long startMillis; unsigned long switchTimeMillis; unsigned int gasLevel; boolean heaterInHighPhase; //----Temperature sensor macros #define DHTPIN 7

// what pin the DHT sensor is connected to

#define DHTTYPE DHT11 // Change to DHT22 if that's what you have DHT dht(DHTPIN, DHTTYPE); //this runs once void setup() { //initalize DHT sensor dht.begin();

//start the clock startMillis = millis(); //initialize network LEDs pinMode(GREEN_LED, OUTPUT); pinMode(RED_LED, OUTPUT); pinMode(YELLOW_LED, OUTPUT); pinMode(ESP_FOUND_LED, OUTPUT);

//initialize MQ-7 LEDs pinMode(HEATING_LED, OUTPUT); pinMode(READING_LED, OUTPUT); pinMode(BUZZER, OUTPUT); //initialize MQ-7 power supply pinMode(RELAY, OUTPUT); //set baud rate Serial.begin(Baud_Rate); delay(1000); //-----connect to network--------Serial.println("Checking if ESP8266 is online..."); connectionStart: Serial.println("AT"); delay(5000);

if (Serial.find("OK")) { digitalWrite(ESP_FOUND_LED, HIGH); Serial.println("ESP8266 found ..."); Serial.println("Trying to connect to network..."); //connect to your wifi netowork bool connected = false; do { networkBlinkConnecting(); connected = connectWiFi(); if (!connected) //signal failure for (int i = 0; i < 3; i++) networkBlinkError(); } while (!connected); Serial.println("Connection achived...."); digitalWrite(YELLOW_LED, HIGH); // indicate connection achived } else { Serial.println("ESP8266 not found..."); Error(); goto connectionStart; }

} //this runs over and over void loop() { if (heaterInHighPhase) { // 5v phase of cycle. see if need to switch low yet if (millis() > switchTimeMillis) { Serial.println("Reading from sensors...."); turnHeaterLow(); } blinkHeating(); } else { // 1.4v phase of cycle. see if need to switch high yet if (millis() > switchTimeMillis) { Serial.println("Heating the gas sensor...."); turnHeaterHigh(); } // Read temperature and humidity float h = dht.readHumidity(); float f = dht.readTemperature(false); unsigned int gasLevel = readGasLevel(); blinkReading(); // Check if any reads failed and exit early (to try again).

if (isnan(h) || isnan(f) || isnan(gasLevel)) { networkBlinkError(); return; } else if (gasLevel >= 60) { tone(BUZZER, 3000); // Send 1KHz sound signal... } else { noTone(BUZZER);

// Stop sound...

} //update ThingSpeak channel with new values updated = updateValues(String(f), String(h), String(gasLevel)); //if update succeeded light up green LED, else light up red LED Serial.println(updated); if (updated) { networkBlinkSending(); } else { networkBlinkError(); } blinkReading(); } }

//----network update function-------------bool updateValues(String temp, String humid, String gasLevel) { //initialize your AT command string String cmd = "AT+CIPSTART=\"TCP\",\""; //add IP address and port cmd += IP; cmd += "\",80"; //connect Serial.println(cmd); delay(500); if (Serial.find("Error")) { return false; } //build GET command, ThingSpeak takes Post or Get commands for updates, I use a Get cmd = GET; //cmd += FIELD1; cmd += temp; cmd += FIELD2; cmd += humid; cmd += FIELD3; cmd += gasLevel;

cmd += "\r\n"; //Use AT commands to send data Serial.print("AT+CIPSEND="); Serial.println(cmd.length()); if (Serial.find(">")) { //send through command to update values Serial.print(cmd); } else { Serial.println("AT+CIPCLOSE"); } if (Serial.find("OK")) { //success! Your most recent values should be online. return true; } else { return false; } } //----network functions-------------boolean connectWiFi() { //set ESP8266 mode with AT commands Serial.println("AT+CWMODE=1"); delay(2000);

//build connection command String cmd = "AT+CWJAP=\""; cmd += SSID; cmd += "\",\""; cmd += PASS; cmd += "\""; //connect to WiFi network and wait 5 seconds Serial.println(cmd); delay(5000); //if connected return true, else false if (Serial.find("OK")) { return true; } else { return false; } } void Error() { networkBlinkError(); Serial.println("Error"); } //----MQ-7 functions-------------void blinkHeating() {

digitalWrite(HEATING_LED, HIGH); delay(200); digitalWrite(HEATING_LED, LOW); delay(200); } void blinkReading() { digitalWrite(READING_LED, HIGH); delay(GAS_LEVEL_READING_PERIOD_MILLIS / 2); digitalWrite(READING_LED, LOW); delay(GAS_LEVEL_READING_PERIOD_MILLIS / 2); } //--read from gas sensor--------unsigned int readGasLevel() { return analogRead(MQ7_ANALOG_IN_PIN); } //----network LEDs-------void networkBlinkSending() { digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HIGH); delay(500); digitalWrite(GREEN_LED, LOW); delay(500); }

void networkBlinkError() { digitalWrite(GREEN_LED, LOW); digitalWrite(RED_LED, HIGH); delay(200); digitalWrite(RED_LED, LOW); delay(200); } void networkBlinkConnecting() { digitalWrite(YELLOW_LED, HIGH); delay(200); digitalWrite(YELLOW_LED, LOW); delay(200); } //--- relay logic void turnHeaterHigh() { // 5v phase digitalWrite(RELAY, HIGH); heaterInHighPhase = true; switchTimeMillis = millis() + MQ7_HEATER_5_V_TIME_MILLIS; } void turnHeaterLow() { // 1.4v phase digitalWrite(RELAY, LOW); heaterInHighPhase = false;

switchTimeMillis = millis() + MQ7_HEATER_1_4_V_TIME_MILLIS; }

67) Arduino Catch The Beat

COMPONENTS AND SUPPLIES

Arduino 101 & Genuino 101 ×

1

×

1

×

1

×

1

Buzzer

Rotary potentiometer (generic)

8x8 led matrix

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT This project is inspired in OSU!Catch the beat and this game consist in catching the falling balls, you have 10 lives, you lose one for every ball you miss and you recover two for every ball you catch getting one point. Every four point the speed increases and you tun out of lives the game ends.

How to do this project: Step 1: Check Arduino connection.

Step 2: Copy and paste the code in new sketch of Arduino IDE. Step 3: Conect the led matrix, buzzer and potentiometer to Arduino.

SCHEMATICS

CODE

int row[] = {2, 7, A5, 5, 13, A4, 12, A2}; int col[] = {6, 11, 10, 3, A3, 4, 8, 9}; int joystick = A0; //es un simple potenciometro int lastUpdate; int puntos = 0; int vidas = 10; int speakerPin = A1; int speed = 16; bool updatedAsteroid = false, updatedPlayer = true; typedef struct coordenada { int x; //cordenada de la columna int y; //cordenada de la fila }COORD; COORD asteroid, jugador; void setup() { // put your setup code here, to run once: for (int i = 0; i < 8; i++) { pinMode(row[i], OUTPUT); pinMode(col[i], OUTPUT); digitalWrite(col[i], HIGH); digitalWrite(row[i], LOW); } pinMode(speakerPin, OUTPUT);

initGame(); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: for(int i = 0; i < 2; i++) { clearScreen(); //limpia la matriz de leds if(lastUpdate == 1) { movePlayer(); } if(lastUpdate == 0) { asteroidFall(); //Serial.print("El asteroide cambia de posicion!!\n"); } lastUpdate = Update(); //actualiza la matriz de leds segun movePlayer() y asteroidFall() delay(speed); } puntuacion(); //calcula la puntuacion y aumenta una vida por punto, cuando el jugador se queda sin vidas se pasa a gameover() para reiniciar la partida if (asteroid.y == 8 || asteroid.y > 8) { initasteroid(); //inizializa un nuevo asteroid cuando el anterior ya ha caido } }

void initGame() { vidas = 10; puntos = 0; speed = 16; initplayer(); initasteroid(); return; } void initplayer() { jugador.x = 3; jugador.y = 7; digitalWrite(col[jugador.y], HIGH); digitalWrite(row[jugador.x], LOW); return; } void initasteroid() { asteroid.x = random(0, 7); asteroid.y = -1; //para que asteroidFall() comienze en 0 nada mas ejecutarse digitalWrite(col[asteroid.x], LOW); digitalWrite(row[asteroid.y], HIGH); return; }

void movePlayer() { int value = analogRead(joystick); value = map(value, 0, 1023, 0, 7); value = constrain(value, 0, 7); //Serial.print("joystickX: "); //Serial.print(jugador.x); //Serial.print("\n"); if(value >= 0 && value 9 && puntos >= 4) { speed--; //aumenta la velocidad del juego (nivel nuevo) puntos = 0; //reiniciamos la puntucion al pasar al siguiente nivel } Serial.print("Puntos: "); Serial.print(puntos); Serial.print("\n"); } if(asteroid.y == jugador.y && asteroid.x != jugador.x) { vidas--; Serial.print("Vidas: "); Serial.print(vidas); Serial.print("\n"); if(vidas == 0) { gameover(); } } return; } void gameover() { //animacion cuando pierdes la partida for(int y = 0; y < 5; y++) { //Serial.print("Animacion: "); //Serial.print(y); //Serial.print("\n");

//bucle que apaga todos los leds de la matriz digitalWrite(speakerPin, HIGH); for(int i = 0; i < 8; i++) { digitalWrite(col[i], HIGH); digitalWrite(row[i], LOW); } delay(500); //bucle que enciende todos los leds de la matriz for(int i = 0; i < 8; i++) { digitalWrite(col[i], LOW); digitalWrite(row[i], HIGH); } digitalWrite(speakerPin, LOW); delay(500); } delay(1000); initGame(); //inicializa una nueva partida return; } 68) Arduino Safepools pH

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

1

×

1

DFRobot pH Sensor DFRobot SparkFun Bluetooth Modem BlueSMiRF Silver

Jumper wires (generic) ×

1

×

1

×

1

×

1

×

1

Temperature Sensor

9V to Barrel Jack Connector

9V battery (generic)

NXP Hexiwear

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

Hot glue gun (generic)

Mini Plastic Container

ABOUT THIS PROJECT The primary objective of this project is to use Hexiwear to monitor the pH and temperature levels of swimming pools. Hexiwear Setup The Hexiwear can be placed anywhere near the bluetooth range of the Hardware Sensor. Using the LCD screen, it displays the Temp and pH Sensor. The Hexiware can be programmed to analyze the data from sensors given the computation of Langelier Saturation Index (LSI). Using the LSI we can calculate if the pool is acidic, alkaline or in normal level. The computation can also give recommendations on how many chemicals to be put on the water to stabilize the level. Hardware Sensor Setup The hardware station prototype is placed inside a 4.3” x 1.9” rectangular plastic container and was created by connecting an Arduino Uno R3 to a pH sensor, temperature sensor, and Bluetooh Module. The power source is connected through a USB cable and power bank. Field Test

We have tested the hardware sensor to Private, Public and School Swimming Pool. Collecting the data from these respondents' pool enabled us to analyze the capability of the hardware. School Pool

Photos from a private school swimming pool. Results We wanted to provide an automated swimming pool water quality monitoring. The development is still in progress. But we hope that through this, may there will be an increased awareness regarding the continuous degradation of the swimming pool water quality as people tend to focus more on the amenities that are offered instead of checking how safe they are. They also intend to contribute to the community by being able to provide a means to make water quality testing more efficient and effective without the unnecessary sacrifice of resources.

SCHEMATICS Connect the sensors and bluetooth module using jumper wires to the Arduino Uno. Bluetooth module to RX/TX Temp Sensor Output(Blue) to Analog 0, GND(Black) to GND and V(Red) to 5V. pH Sensor Output to Analog 1(Green), GND(Black) to GND and V(Red) to 5V.

CODE #include

#include #include

#define SensorPin A0 Input 0 #define Offset 0.00

//pH meter Analog output to Arduino Analog //deviation compensate

#define LED 13 #define samplingInterval 20 #define printInterval 800 #define ArrayLenth 40

//times of collection

int pHArray[ArrayLenth]; //Store the average value of the sensor feedback int pHArrayIndex=0; #define tempOffSet 0.00 #define DEBUG false #define responseTime 20 #define ONE_WIRE_BUS 4 on the Arduino

// Data wire is plugged into port 2

OneWire oneWire(ONE_WIRE_BUS); communicate with any OneWire

// Setup a oneWire instance to

//devices (not just Maxim/Dallas temperature ICs) DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.

SoftwareSerial bluetoothSerial(2, 3);

// RX, TX

void setup() { //setup RGB LED as indicator instead of softserial pinMode(12,OUTPUT); digitalWrite(12,HIGH); // Open serial communications and wait for port to open: Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } bluetoothSerial.begin(115200); while (!bluetoothSerial) { ; // wait for serial port to connect. Needed for Leonardo only } sendTobluetooth("AT+CWMODE=2",responseTime,DEBUG); // configure as access point sendTobluetooth("AT+CIFSR",responseTime,DEBUG); // get ip address sendTobluetooth("AT+CIPMUX=1",responseTime,DEBUG); // configure for multiple connections sendTobluetooth("AT+CIPSERVER=1,80",responseTime,DEBUG); // turn on server on port 80

sendToUno("Safepools.pH Hardware is ready!",responseTime,DEBUG);

}

void loop() { ///// Read pH Regularly ////// static unsigned long samplingTime = millis(); static unsigned long printTime = millis(); static float pHValue,voltage; if(millis()-samplingTime > samplingInterval) { pHArray[pHArrayIndex++]=analogRead(SensorPin); if(pHArrayIndex==ArrayLenth)pHArrayIndex=0; voltage = avergearray(pHArray, ArrayLenth)*5.0/1024; pHValue = 3.5*voltage+Offset; samplingTime=millis(); } if(Serial.available()>0){ String message = readSerialMessage(); if(find(message,"debugdebugBluetooth:")){ String result = sendTobluetooth(message.substring(13,message.length()),responseTime,DEBUG); if(find(result,"OK")) sendData("\nOK");

else sendData("\nEr"); } } if(bluetoothSerial.available()>0){ String message = readbluetoothSerialMessage(); if(find(message,"debugBluetooth:")){ String result = sendTobluetooth(message.substring(8,message.length()),responseTime,DEBUG); if(find(result,"OK")) sendData("\n"+result); else sendData("\nATCE1001"); Failed Executing statement

//At command ERROR CODE for

}else if(find(message,"getT")){ float temp = 0; sensors.requestTemperatures(); temperatures

// Send the command to get

temp = sensors.getTempCByIndex(0); sensors.requestTemperatures(); temperatures

// Send the command to get

temp = sensors.getTempCByIndex(0); if(temp==85) sendData("\nTE1001"); INITIALIZE

//Temperature ERROR CODE for

else if(temp==0 || temp==-127) sendData("\nTE1002"); CONNECTED

//Temperature ERROR CODE for NOT

else{ String temperature = ""; temperature+=temp+tempOffSet; sendData("\n"+temperature); } }else if(find(message,"getP")){ //sending ph level: if(pHValue==0){ sendData("\nPE1001");

//pH ERROR CODE for NOT OPEN

}else{ String ph = ""; ph+=pHValue; sendData("\n"+ph); } }else if(find(message,"pHOff")){ //sending ph level: digitalWrite(12,0); }else if(find(message,"pHOn")){ //sending ph level: digitalWrite(12,1); } else{ sendData("\nErrRead");

//Command ERROR CODE for

UNABLE TO READ } } delay(responseTime); } double avergearray(int* arr, int number){ int i; int max,min; double avg; long amount=0; if(number prevVolume) { tv.setMute(false); prevMute = false; for (int k = prevVolume + 1 ; k=tv.getVolume(); k--) { sendIR(volDown); Serial.println("Volume changed:"+String(tv.getVolume())+" Set:"+String(k)); } prevVolume = tv.getVolume(); } // Mute changed if (tv.getMute() != prevMute && tv.getMute()) { prevMute = tv.getMute(); sendIR(mute); Serial.println("Mute changed:"+String(tv.getMute())); } else if (tv.getMute() != prevMute && !tv.getMute()) { prevMute = tv.getMute(); sendIR(mute); Serial.println("Mute changed:"+String(tv.getMute())); } // Channel changed if (tv.getChannel() != prevChannel) { int newChannel = tv.getChannel(); if (newChannel > 0 && newChannel < 10) { sendIR(chan[newChannel-1]); } else if (newChannel > 9) { if (newChannel > prevChannel) {

for (int ch = prevChannel; ch < newChannel; ch++) { sendIR(chanUp); Serial.println("Chan requested:"+String(newChannel)+" Set:"+String(ch)); } } else if (newChannel < prevChannel) { for (int ch = prevChannel; ch > newChannel; ch--) { sendIR(chanDown); Serial.println("Chan requested:"+String(newChannel)+" Set:"+String(ch)); } } } prevChannel = newChannel; Serial.println("Channel changed:"+String(tv.getChannel())); } // On/Off changed if (tv.getSwitch() != prevSwitch) { prevSwitch = tv.getSwitch(); if (tv.getSwitch()) { sendIR(chan[6]); } else { sendIR(onoff); } Serial.println("Switch changed:"+String(tv.getSwitch())); } Part 4: Amazon Alexa We will now need the Amazon Alexa app which can be downloaded from the Apple App Store or the Google Play Store. Once installed, login with your existing account or create a new one. Let's go through the steps necessary to install the Arduino Alexa Skill and configure it to access and control our TV. We'll follow the sequence of images below to see all the required steps.

Tap on "Devices"

2/11: Let's now enable our Smart Home Skills

We'll be presented with the featured ones. Time to search for what we need :) We're done, it's now time to voice control our TV asking things like ”Alexa, turn the volume up on TV.” ”Alexa, mute TV" or “Alexa, unmute TV.” ”Alexa, next channel on TV.” SCHEMATICS

CODE /* Sketch generated by the Arduino IoT Cloud Thing "TVRemoteController" https://create.arduino.cc/cloud/things/994d9efc-9c38-4a4c-9d3c-

454106da00f6 Arduino IoT Cloud Properties description The following variables are automatically generated and updated when changes are made to the Thing properties CloudTelevision tv; Properties which are marked as READ/WRITE in the Cloud Thing will also have functions which are called when their values are changed from the Dashboard. These functions are generated with the Thing and added at the end of this sketch. */ #include "thingProperties.h" #include const unsigned int chan[9][67] = { {4450,4500, 550,1700, 500,1700, 550,1700, 550,550, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,1700, 550,1700, 500,600, 500,600, 550,550, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,600, 500,600, 550,550, 550,600, 500,600, 550,1700, 500,1700, 550,600, 500,1700, 550,1700, 550,1700, 500,1700, 550,1700, 500}, {4500,4500, 550,1700, 500,1700, 550,1700, 550,550, 550,550, 550,600, 500,600, 550,600, 500,1700, 550,1700, 500,1700, 550,600, 500,600, 550,550, 550,600, 500,600, 550,1700, 500,600, 550,1700, 500,600, 550,550, 550,600, 500,600, 550,550, 550,650, 450,1700,

550,600, 500,1700, 550,1700, 500,1700, 550,1700, 550,1700, 500}, {4500,4500, 500,1700, 550,1700, 550,1700, 500,600, 550,550, 550,600, 500,600, 550,550, 550,1700, 500,1700, 550,1700, 550,550, 550,600, 500,600, 550,550, 550,600, 500,600, 550,1700, 500,1700, 550,600, 550,550, 550,550, 550,600, 550,550, 550,1700, 500,600, 550,550, 550,1700, 550,1650, 550,1700, 550,1700, 500,1700, 600}, {4450,4450, 550,1700, 550,1700, 500,1700, 550,600, 500,600, 550,550, 600,550, 500,600, 550,1700, 500,1700, 550,1700, 550,550, 550,600, 500,600, 550,550, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,1700, 550,1700, 500,600, 550,1700, 500,1700, 550,1700, 550,1700, 500}, {4500,4500, 500,1700, 550,1700, 550,1700, 550,550, 550,550, 550,550, 600,550, 550,550, 550,1700, 550,1650, 550,1700, 550,550, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,600, 500,600, 550,1700, 500,600, 550,550, 550,600, 550,550, 550,550, 550,1700, 550,1700, 500,600, 550,1700, 500,1700, 550,1700, 550,1700, 500}, {4500,4500, 550,1650, 550,1700, 550,1700, 500,600, 550,550, 550,600, 500,600, 500,600, 550,1700, 500,1700, 550,1700, 550,550, 600,550, 500,600, 550,550, 600,550, 550,550, 550,1700, 500,600, 550,1700, 500,600, 550,550, 550,600, 500,600, 550,1700, 500,600, 550,1700, 500,600, 550,1650, 600,1650, 550,1700, 550,1650, 600}, {4500,4500, 550,1700, 500,1700, 550,1750, 500,550, 550,600, 500,650, 500,550, 550,550, 550,1750, 500,1700, 500,1700, 550,650, 450,650, 500,550, 550,600, 500,650, 500,550, 550,600, 500,1700, 550,1750, 500,600, 500,550, 550,600, 500,650, 500,1750, 450,1700, 550,600, 500,650, 500,1700, 500,1700, 550,1750, 500,1700, 500}, {4450,4550, 500,1700, 550,1700, 550,1650, 550,600, 500,600, 550,550, 550,600, 500,600, 550,1700, 500,1700, 550,1700, 550,550, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,600, 500,1700, 550,1700, 500,600, 550,550, 550,650, 450,600, 550,550, 550,1700, 550,550, 550,600, 500,1700, 550,1700, 550,1700, 500,1700, 550}, {4450,4500, 550,1700, 550,1700, 500,1700, 550,600, 500,600,

550,550, 550,600, 500,600, 550,1700, 500,1700, 550,1700, 500,600, 550,550, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,1700, 550,1700, 500,600, 550,550, 550,550, 550,600, 500,1700, 550,600, 500,600, 550,550, 550,1700, 550,1700, 500,1700, 550,1700, 550} }; const unsigned int volUp[67] = {4500,4500, 550,1700, 500,1750, 500,1700, 550,600, 500,600, 500,600, 550,550, 550,600, 500,1700, 550,1700, 550,1700, 500,650, 450,600, 550,600, 500,650, 450,650, 500,1700, 500,1750, 500,1750, 500,550, 550,600, 500,650, 500,550, 550,600, 500,650, 500,600, 500,600, 500,1700, 550,1750, 450,1750, 500,1700, 550,1700, 500}; const unsigned int volDown[67] = {4450,4550, 500,1700, 550,1700, 550,1650, 550,600, 550,550, 550,600, 500,600, 500,600, 550,1700, 500,1700, 550,1700, 550,550, 550,600, 500,600, 550,550, 550,600, 500,1700, 550,1700, 550,600, 500,1700, 550,600, 500,600, 500,600, 550,550, 550,600, 500,650, 500,1700, 500,650, 500,1700, 500,1750, 500,1700, 550,1700, 500}; const unsigned int chanUp[67] = {4500,4450, 550,1700, 550,1650, 550,1700, 550,550, 550,600, 550,550, 550,550, 600,550, 550,1650, 550,1700, 550,1650, 600,550, 550,550, 550,600, 500,600, 550,550, 550,550, 550,1700, 550,550, 600,550, 550,1650, 550,600, 550,550, 550,550, 550,1700, 550,550, 550,1700, 550,1700, 550,550, 550,1650, 600,1650, 550,1700, 550}; const unsigned int chanDown[67] = {4500,4450, 600,1650, 550,1700, 550,1650, 550,600, 550,550, 550,550, 550,600, 500,600, 550,1700, 500,1700, 550,1700, 550,550, 550,600, 550,550, 550,550, 550,550, 600,550, 550,550, 550,600, 500,600, 550,1650, 600,550, 550,550, 550,550, 600,1650, 550,1700, 500,1700, 600,1650, 550,550, 600,1650, 550,1700, 500,1700, 550};

const unsigned int onoff[67] = {4400,4600, 450,1800, 400,1800, 450,1750, 500,600, 450,750, 400,650, 450,700, 400,700, 400,1800, 450,1750, 450,1800, 450,650, 450,650, 450,700, 400,700, 450,650, 450,650, 450,1800, 450,600, 500,650, 400,700, 450,650, 500,600, 500,700, 400,1850, 400,700, 400,1750, 450,1800, 450,1750, 500,1700, 450,1800, 450,1850, 350}; const unsigned int mute[67] = {4550,4450, 550,1700, 450,1750, 500,1700, 550,600, 600,450, 600,550, 550,550, 600,550, 550,1650, 550,1650, 600,1650, 550,550, 600,500, 550,600, 550,500, 600,500, 600,1650, 600,1600, 600,1650, 600,1650, 550,550, 500,600, 550,550, 500,650, 500,600, 500,600, 500,600, 500,600, 500,1700, 550,1700, 500,1700, 550,1700, 500}; IRsend irsend; const int freq = 38; bool first; int prevChannel; int prevVolume; bool prevSwitch; bool prevMute; void setup() { // Initialize serial and wait for port to open: Serial.begin(9600); // This delay gives the chance to wait for a Serial Monitor without blocking if none is found delay(1500);

// Defined in thingProperties.h initProperties(); // Connect to Arduino IoT Cloud ArduinoCloud.begin(ArduinoIoTPreferredConnection); setDebugMessageLevel(2); ArduinoCloud.printDebugInfo(); first = true; pinMode(LED_BUILTIN, OUTPUT); } void loop() { ArduinoCloud.update(); } void sendIR(const unsigned int buf[]) { digitalWrite(LED_BUILTIN, HIGH); irsend.sendRaw(buf, 67, freq); delay(300); digitalWrite(LED_BUILTIN, LOW); } void onTvChange() { Serial.println("=================="); Serial.println("Switch:"+String(tv.getSwitch())); Serial.println("Volume:"+String(tv.getVolume()));

Serial.println("Channel:"+String(tv.getChannel())); Serial.println("Mute:"+String(tv.getMute())); Serial.println("=================="); if (first){ prevSwitch = tv.getSwitch(); prevVolume = tv.getVolume(); prevChannel = tv.getChannel(); prevMute = tv.getMute(); first = false; return; } // Volume changed if (tv.getVolume() > prevVolume) { tv.setMute(false); prevMute = false; for (int k = prevVolume + 1 ; k=tv.getVolume(); k--) { sendIR(volDown); Serial.println("Volume changed:"+String(tv.getVolume())+" Set:"+String(k)); } prevVolume = tv.getVolume(); } // Mute changed if (tv.getMute() != prevMute && tv.getMute()) { prevMute = tv.getMute(); sendIR(mute); Serial.println("Mute changed:"+String(tv.getMute())); } else if (tv.getMute() != prevMute && !tv.getMute()) { prevMute = tv.getMute(); sendIR(mute); Serial.println("Mute changed:"+String(tv.getMute())); } // Channel changed if (tv.getChannel() != prevChannel) { int newChannel = tv.getChannel(); if (newChannel > 0 && newChannel < 10) { sendIR(chan[newChannel-1]); } else if (newChannel > 9) { if (newChannel > prevChannel) {

for (int ch = prevChannel; ch < newChannel; ch++) { sendIR(chanUp); Serial.println("Chan requested:"+String(newChannel)+" Set:"+String(ch)); } } else if (newChannel < prevChannel) { for (int ch = prevChannel; ch > newChannel; ch--) { sendIR(chanDown); Serial.println("Chan requested:"+String(newChannel)+" Set:"+String(ch)); } } } prevChannel = newChannel; Serial.println("Channel changed:"+String(tv.getChannel())); } // On/Off changed if (tv.getSwitch() != prevSwitch) { prevSwitch = tv.getSwitch(); if (tv.getSwitch()) { sendIR(chan[6]); } else { sendIR(onoff); } Serial.println("Switch changed:"+String(tv.getSwitch())); }

}

80) Arduino Rickoll Box

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

1

Breadboard (generic)

Buzzer

×

1

×

1

×

1

×

1

×

1

×

2

×

2

×

12

Photo resistor

LED (generic)

Single Turn Potentiometer- 10k ohms

SparkFun Pushbutton switch 12mm

Resistor 10k ohm

Resistor 560 ohm Jumper wires (generic)

ABOUT THIS PROJECT Basically, this involves a surprise piezo rendition of the song “Never Gonna Give You Up” by Rick Astley that plays when the box is opened and pauses when the box is closed. When the box is reopened, the song picks up where it left off. While the song is playing, an LED blinks to the notes of the music, and the Serial monitor outputs the lyrics in time with the actual song. A potentiometer can be turned to adjust the volume of the music. A fun button also exists that, when pressed, makes the song get faster. It can be pressed a few more times to make the tempo get progressively faster until it loops back around to the original tempo. I/O Components Inputs: Potentiometer –used as a dial to adjust volume of piezo output Photoresistor—determines whether box is open or closed (light or dark) Button – can be pressed to make song get progressively faster Outputs: Piezo – used to create sound for song LED – blinks to notes of song Serial Output – prints out words of song

Circuit connections shown outside of box for clarity.

Circuit connections shown outside of box for clarity. Methods In order to play music, the song first had to be transcribed into a form that could be interpreted in code. The notes were determined by listening to the song and matching them on the piano. The rhythms were determined by counting and clapping out the song to a consistent set of beats. In the code, these notes were stored in arrays as their respective frequencies, i.e. A4=440 Hz. This is how the Piezo outputs noise; it generates sound at specified frequencies to create a pitch. All frequencies required for the song were defined at the beginning of the code. For the rhythm of the song, relative durations of notes were stored in arrays, and these durations were later multiplied by a constant beat length in order to determine the full duration of the note. A gap 30% of the length of the previous note was introduced to create space between

notes. The full song was divided into the intro, first verse, and chorus, which were set to play in the following order indefinitely: chorus, first verse, chorus, intro, intro, first verse etc. Finally, these arrays of notes and rhythms could be iterated through on a step-by-step basis, which allowed for the integration of visual outputs, such as light and lyrics. To actually output the sound from the piezo, the tone function was used, which handles the tone duration with its own independent timer. This necessitated additional delay calls in order to keep the notes on time with other parts of the code. A light threshold was generated during setup in order to determine when the box would be open (bright) and closed (dark) in order to play and pause the song. In order to take input from the button at any time, since the state change is instantaneous (as opposed to the photoresistor, which produces continuous digital input), an interrupt was attached to the button pin in order to detect when it was pressed. Interrupts, initialized in the setup, are always listening for state changes; when the specified change is detected, the program immediately switches to handling the interrupt with a specified method and then picks up where it left off. This is a good way to handle inputs because it allows them to be read at any time, even if another portion of code is executing. Interrupts just have to be handled carefully, and any variable that is changed by them should be declared as volatile. Future Modifications Add a servo, and take a mini Rick Astley to its arm to dance to the music. Replace standard LED with RGB LED, and cycle through colors during the song. Add more standard LEDs to blink to the beat of the music. Whenever Rick Astley sings "Never gonna give you up," play Darude "Sandstorm," and start flashing LEDs at random.

SCHEMATICS

CODE /* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. DISCLAIMER: The song "Never Gonna Give You Up" by Rick Astley is not the creative property of the author. This code simply plays a Piezo buzzer rendition of the song. */ #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define

a3f b3f b3 c4 c4s e4f f4 a4f b4f b4 c5 c5s e5f f5 f5s a5f

#define rest

208 233 247 261 277 311 349 415 466 493 523 554 622 698 740 831

// 208 Hz // 233 Hz // 247 Hz // 261 Hz MIDDLE C // 277 Hz // 311 Hz // 349 Hz // 415 Hz // 466 Hz // 493 Hz // 523 Hz // 554 Hz // 622 Hz // 698 Hz // 740 Hz // 831 Hz

-1

int piezo = 7; int led = 9; int button = 2; int sensor = A0; volatile int beatlength = 100; // determines tempo float beatseparationconstant = 0.3; int threshold;

int a; // part index int b; // song index int c; // lyric index boolean flag; // Parts 1 and 2 (Intro) int song1_intro_melody[] = {c5s, e5f, e5f, f5, a5f, f5s, f5, e5f, c5s, e5f, rest, a4f, a4f}; int song1_intro_rhythmn[] = {6, 10, 6, 6, 1, 1, 1, 1, 6, 10, 4, 2, 10}; // Parts 3 or 5 (Verse 1) int song1_verse1_melody[] = { rest, c4s, c4s, c4s, c4s, e4f, rest, c4, b3f, a3f, rest, b3f, b3f, c4, c4s, a3f, a4f, a4f, e4f, rest, b3f, b3f, c4, c4s, b3f, c4s, e4f, rest, c4, b3f, b3f, a3f, rest, b3f, b3f, c4, c4s, a3f, a3f, e4f, e4f, e4f, f4, e4f, c4s, e4f, f4, c4s, e4f, e4f, e4f, f4, e4f, a3f, rest, b3f, c4, c4s, a3f, rest, e4f, f4, e4f }; int song1_verse1_rhythmn[] = { 2, 1, 1, 1, 1, 2, 1, 1, 1, 5, 1, 1, 1, 1, 3, 1, 2, 1, 5, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4, 5, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 3, 1, 1, 1, 3 }; char* lyrics_verse1[] = { "We're ", "no ", "strangers ", "", "to ", "love ", "", "\r\n", "You ", "know ", "the ", "rules ", "and ", "so ", "do ", "I\r\n", "A ", "full ", "commitment's ", "", "", "what ", "I'm ", "thinking ", "", "of", "\r\n", "You ", "wouldn't ", "", "get ", "this ", "from ", "any ", "", "other ", "", "guy\r\n", "I ", "just ", "wanna ", "", "tell ", "you ", "how ", "I'm ", "feeling", "\r\n", "Gotta ", "", "make ", "you ", "understand", "", "\r\n" }; // Parts 4 or 6 (Chorus)

int song1_chorus_melody[] = { b4f, b4f, a4f, a4f, f5, f5, e5f, b4f, b4f, a4f, a4f, e5f, e5f, c5s, c5, b4f, c5s, c5s, c5s, c5s, c5s, e5f, c5, b4f, a4f, a4f, a4f, e5f, c5s, b4f, b4f, a4f, a4f, f5, f5, e5f, b4f, b4f, a4f, a4f, a5f, c5, c5s, c5, b4f, c5s, c5s, c5s, c5s, c5s, e5f, c5, b4f, a4f, rest, a4f, e5f, c5s, rest }; int song1_chorus_rhythmn[] = { 1, 1, 1, 1, 3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2, 1, 1, 1, 1, 3, 3, 3, 1, 2, 2, 2, 4, 8, 1, 1, 1, 1, 3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2, 1, 1, 1, 1, 3, 3, 3, 1, 2, 2, 2, 4, 8, 4 }; char* lyrics_chorus[] = { "Never ", "", "gonna ", "", "give ", "you ", "up\r\n", "Never ", "", "gonna ", "", "let ", "you ", "down", "", "\r\n", "Never ", "", "gonna ", "", "run ", "around ", "", "", "", "and ", "desert ", "", "you\r\n", "Never ", "", "gonna ", "", "make ", "you ", "cry\r\n", "Never ", "", "gonna ", "", "say ", "goodbye ", "", "", "\r\n", "Never ", "", "gonna ", "", "tell ", "a ", "lie ", "", "", "and ", "hurt ", "you\r\n" }; void setup() { pinMode(piezo, OUTPUT); pinMode(led, OUTPUT); pinMode(button, INPUT_PULLUP); pinMode(sensor, INPUT); attachInterrupt(digitalPinToInterrupt(button), getFaster, FALLING); digitalWrite(led, LOW); Serial.begin(9600); flag = false; a = 4; b = 0; c = 0; threshold = analogRead(sensor) + 250; }

void loop() { int sensorreading = analogRead(sensor); if (sensorreading < threshold) { // if bright, play flag = true; } else if (sensorreading > threshold) { // if dark, pause flag = false; } // play next step in song if (flag == true) { play(); } } void play() { int notelength; if (a == 1 || a == 2) { // intro notelength = beatlength * song1_intro_rhythmn[b]; if (song1_intro_melody[b] > 0) { digitalWrite(led, HIGH); tone(piezo, song1_intro_melody[b], notelength); } b++; if (b >= sizeof(song1_intro_melody) / sizeof(int)) { a++; b = 0; c = 0; } } else if (a == 3 || a == 5) { // verse notelength = beatlength * 2 * song1_verse1_rhythmn[b]; if (song1_verse1_melody[b] > 0) { digitalWrite(led, HIGH); Serial.print(lyrics_verse1[c]); tone(piezo, song1_verse1_melody[b], notelength); c++; } b++; if (b >= sizeof(song1_verse1_melody) / sizeof(int)) { a++; b = 0;

c = 0; } } else if (a == 4 || a == 6) { // chorus notelength = beatlength * song1_chorus_rhythmn[b]; if (song1_chorus_melody[b] > 0) { digitalWrite(led, HIGH); Serial.print(lyrics_chorus[c]); tone(piezo, song1_chorus_melody[b], notelength); c++; } b++; if (b >= sizeof(song1_chorus_melody) / sizeof(int)) { Serial.println(""); a++; b = 0; c = 0; } } delay(notelength); noTone(piezo); digitalWrite(led, LOW); delay(notelength * beatseparationconstant); if (a == 7) { // loop back around to beginning of song a = 1; } } void getFaster() { // decrease beat length in order to increase tempo beatlength = beatlength / 2; if (beatlength < 20) { // loop back to original tempo beatlength = 100; } }

81) Arduino A Very Compact Alarm with Card Reader and Real Time Clock

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

PHPoC Bread Board ×

1

×

2

×

2

×

1

×

1

×

1

×

1

LED (generic)

Resistor 221 ohm

Ultrasonic Sensor - HC-SR04 (Generic)

Buzzer

RC522 Card Reader Real Time Clock

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT This is my first project released on Hackster and every suggestion is accepted. Well, I've made this alarm just for fun and I hope you will like it! How does the alarm work? In order to see from the image to start the alarm, you must put the correct magnetic card on the RC522 Card Reader. If the card is indeed correct, the alarm will turn on automatically (green LED: on; red LED: off), but if the card isn't correct, nothing is happening (green LED: off; red LED: on). When the alarm is started, the HC-SR04 Ultrasonic Sensor will capture any movement in front of it. To shut down the alarm, we will again put the correct magnetic card on RC522 Card Reader (green LED: off; red LED: on). What if you forget to turn on the alarm before going to sleep? We can go to sleep without activating the alarm because the Real Time Clock will activate the alarm at a certain hour. Here you can find some code explanation: On line 29, you can set the code of your magnetic card. String codiceAutorizzato = "5545A93980"; On line 53, you can schedule the automatic start of the alarm (24 hours format). if (orario=="21:56" && statoattivato==0) On line 65, you can set the maximum distance from which the sensor

works (it must be expressed in centimeters). Beyond this limit, the sensor won't work and no movement will be notice. if (sr04.Distance()= (1000 * 60 * timearro) ) { digitalWrite(POMPES, !digitalRead(POMPES)); //if so, change the state of the LED. Uses a neat trick to change the state startMillis = currentMillis1; //IMPORTANT to save the start time of the current LED state. } } void recvWithStartEndMarkers() { static boolean recvInProgress = false; static byte ndx = 0; char startMarker = ''; char rc; while (Serial1.available() > 0 && newData == false) { rc = Serial1.read();

if (recvInProgress == true) { if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string recvInProgress = false; ndx = 0; newData = true; } } else if (rc == startMarker) { recvInProgress = true; } } }

void parseData() { char * strtokIndx; // this is used by strtok() as an index //strtokIndx = strtok(tempChars,","); // get the first part - the string //strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC strtokIndx = strtok(tempChars, ","); // this continues where the previous call left off integerFromPC = atoi(strtokIndx); strtokIndx = strtok(NULL, ","); int1 = atoi(strtokIndx); strtokIndx = strtok(NULL, ","); int2 = atoi(strtokIndx); strtokIndx = strtok(NULL, ","); int3 = atoi(strtokIndx); strtokIndx = strtok(NULL, ","); int4 = atoi(strtokIndx);

strtokIndx = strtok(NULL, ","); int5 = atoi(strtokIndx); strtokIndx = strtok(NULL, ","); int6 = atoi(strtokIndx);

} //=========================================fonction recu depuis nodemcu============================ void showParsedData() { if (integerFromPC == 1) { digitalWrite(LAMPES, HIGH); EEPROM.update(addr, 1); integerFromPC = 250; } if (integerFromPC == 0) { digitalWrite(LAMPES, LOW); EEPROM.update(addr, 2); integerFromPC = 250; } if (integerFromPC == 4) { digitalWrite(POMPES, HIGH); integerFromPC = 250; } if (integerFromPC == 5) { digitalWrite(POMPES, LOW); integerFromPC = 250; } if (integerFromPC == 9 && int1 != 0 ) {

int timearro = int1; EEPROM.update(9, timearro); integerFromPC = 250; int1 = 0; } } void formulair () { if (integerFromPC == 6 && int1 != 0 && int2 != 0) {

int maxteau = int1; int minteau = int2; EEPROM.update(2, maxteau); EEPROM.update(3, minteau); Serial.println(maxteau); Serial.println(minteau); integerFromPC = 250; int1 = 0; int2 = 0; } } void formulair1 () { if (integerFromPC == 7 && int3 != 0 ) { int OnHour = int3; int OnMin = int4; int OffHour = int5; int OffMin = int6; EEPROM.update(4, OnHour); EEPROM.update(5, OnMin); EEPROM.update(6, OffHour); EEPROM.update(7, OffMin); Serial.println(OnHour); Serial.println(OnMin); Serial.println(OffHour); Serial.println(OffMin); integerFromPC = 250; } } void tdsva () { if (integerFromPC == 8 && int1 != 0 ) { int tdsval = int1; EEPROM.update(8, tdsval); Serial.println(tdsval * 10); integerFromPC = 250; } } void settds() { int tdsval = 10 * EEPROM.read(8); //10* valeur epprom car max 256 impossible de stocker 1000 comme valeur mais 100*10 c'est possible unsigned long currentMillis3 = millis(); if (tdsValue 150) { currentMillis4 = millis(); //get the current "time" (actually the number of milliseconds since the program started) if (currentMillis4 - startMillis >= 8000 ) { digitalWrite(moteurB_1, !digitalRead(moteurB_1)); //if so, change the state of the LED. Uses a neat trick to change the state startMillis1 = currentMillis4; //IMPORTANT to save the start time of the current LED state. } previousMillis3 = currentMillis3; cleanup = true; } if (tdsValue >= tdsval && cleanup == true ) { digitalWrite(moteurB_1, LOW); digitalWrite(moteurB_2, HIGH); freshtds = true; cleanup = false; perioff = false; } if (currentMillis3 - previousMillis3 > nettoyage && perioff == false ) { digitalWrite(moteurB_1, LOW); digitalWrite(moteurB_2, LOW); perioff = true; } if (currentMillis3 - previousMillis3 > periodtds && perioff == true) { Serial.print("freshtds false"); freshtds = false; } } void loop() { recvWithStartEndMarkers(); if (newData == true) { strcpy(tempChars, receivedChars); // this temporary copy is necessary to protect the original data // because strtok() used in parseData() replaces the commas with \0 parseData(); showParsedData(); newData = false;

} state(); sensor(); tdsva(); setpompe(); myRTC.updateTime(); settds(); formulair(); formulair1(); timmer(); data(); flcd(); average(); setwater(); } void state() { maxteau = EEPROM.read(2); minteau = EEPROM.read(3); OnHour = EEPROM.read(4); OnMin = EEPROM.read(5); OffHour = EEPROM.read(6); OffMin = EEPROM.read(7); tdsval = 10 * EEPROM.read(8); timearro = EEPROM.read(9); analog.update(); ledstate = digitalRead(LAMPES); pompestate = digitalRead(POMPES); } void sensor() { sensors.requestTemperatures(); temperature = sensors.getTempCByIndex(0); humi = dht.readHumidity(); temp = dht.readTemperature(); valeur_brute = analog.getValue(); tbox = valeur_brute * (5.0 / 1023.0 * 100.0); } void setwater() { if (temperature >= maxteau && temperature != -127 && temperature != 0) {

digitalWrite(RELAY1, HIGH); } else if (temperature 40U) //every 40 milliseconds,read the analog value from the ADC { analogSampleTimepoint = millis(); analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin); //read the analog value and store into the buffer analogBufferIndex++; if (analogBufferIndex == SCOUNT) analogBufferIndex = 0; } static unsigned long printTimepoint = millis(); if (millis() - printTimepoint > 800U) { printTimepoint = millis(); for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++) analogBufferTemp[copyIndex] = analogBuffer[copyIndex]; averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value float compensationCoefficient = 1.0 + 0.02 * (temperature - 25.0); //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0)); float compensationVolatge = averageVoltage / compensationCoefficient; //temperature compensation tdsValue = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5; //convert voltage value to tds value } }

void recorddata() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis > 1000) { previousMillis = currentMillis; //Serial.print("Current Date / Time: "); // Serial.print(myRTC.dayofmonth); //You can switch between day and month if you're using American system && myRTC.minutes == OnMin // Serial.print("/"); // Serial.print(myRTC.month); // Serial.print("/"); // Serial.print(myRTC.year); // Serial.print(" "); // Serial.print(myRTC.hours); // Serial.print(":"); //Serial.print(myRTC.minutes); // Serial.print(":"); // Serial.println(myRTC.seconds); // Serial.print("Humidity: "); // Serial.print(humi); // Serial.println(" %"); // Serial.print("Temp air: "); //Serial.print(temp); // Serial.println(" Celsius"); // Serial.print("Temp H2O ;"); // Serial.print(temperature); // Serial.println(" Celsius"); // Serial.print("TDS Value:"); // Serial.print(tdsValue, 0); // Serial.println("ppm"); //Serial.print("Temp box: "); // Serial.println(tbox, 1); // Serial.println(" Celsius"); File dataFile = SD.open("datalog1.txt", FILE_WRITE); delay(1); dataFile.println(temperature); delay(1); dataFile.close(); } } void timmer() { if (myRTC.hours == OnHour && myRTC.minutes == OnMin ) {

EEPROM.update(addr, 1); digitalWrite(LAMPES, HIGH); delay(5); } else if (myRTC.hours == OffHour && myRTC.minutes == OffMin ) { // add && myRTC.minutes == OnMin ; (myRTC.hours == OffHour && myRTC.minutes == OffMin){ EEPROM.update(addr, 2); digitalWrite(LAMPES, LOW); delay(5); } } void data() { if (integerFromPC == 3) { Serial1.print(""); Serial1.println(""); } }

void flcd() { lcd.setCursor(0, 0); lcd.print("T Eau:"); lcd.print(temperature, 1); lcd.print((char)223); lcd.setCursor(12, 0); lcd.print("Hum:"); lcd.print(humi, 0); lcd.print(" % "); lcd.print("AP Grow Box V1"); lcd.print(" "); lcd.write(byte(1)); lcd.write(byte(2)); lcd.write(byte(3)); lcd.write(byte(4)); lcd.setCursor(0, 1); lcd.print("T Air:"); lcd.print(temp, 1); lcd.print((char)223); lcd.setCursor(12, 1); lcd.print("TDS:"); lcd.print(tdsValue, 0); lcd.print(" ppm "); lcd.print("T Box:"); lcd.print(tbox, 1); lcd.print((char)223); lcd.print(" "); lcd.write(byte(5)); lcd.write(byte(6)); lcd.write(byte(7)); lcd.write(byte(8)); lcd.scrollDisplayLeft(); }

86) Arduino Nano 7SEG Clock + Temp + Humid

COMPONENTS AND SUPPLIES 7 Segment LED Display, InfoVue ×

4

×

1

Arduino Nano R3

DHT22 Temperature Sensor

ABOUT THIS PROJECT I need to control the humidity and temperature of some carnivorous plants in the greenhouse, this requires constant temperatures and humidity all year round, plus I have inserted a clock that has proved very useful when I spend a lot of time in the greenhouse. I ordered the RTC form and I'm waiting for it to arrive. As soon as it is available I will modify and update the program to add the more precise RTC.

SCHEMATICS

CODE

#include #include #include #include DHT dht(A2,DHT22); SevSeg Display; char text[10][6]; int i = 0; unsigned long timer; //----------------------SET OROLOGIO const unsigned long period = 1000; //durata 1 sec. const unsigned long led_period = 500; //durata lampeggio : unsigned long startMillis; unsigned long led_startMillis; unsigned long currentMillis; unsigned long led_currentMillis; const int hrs_btn = A0; //set ore const int min_btn = A1; //set minuti const int ledPin = 13; //pin lampeggio : int Hrs = 0; int Min = 0; int Sec = 0; int Time = 0000; int ledState = HIGH; void setup() { pinMode(hrs_btn, INPUT_PULLUP); pinMode(min_btn, INPUT_PULLUP); pinMode(ledPin, OUTPUT); byte numDigits = 4; byte digitPins[] = {12, 10, 9, 11}; //byte digitPins[] = {11, 9, 10, 12}; byte segmentPins[] = {2, 3, 4, 5, 6, 7, 8,0}; bool resistorsOnSegments = false; // 'false' means resistors are on digit pins byte hardwareConfig = COMMON_CATHODE; // See README.md for options

bool updateWithDelays = false; // Default 'false' is Recommended bool leadingZeros = true; // Use 'true' if you'd like to keep the leading zeros bool disableDecPoint = true; // Use 'true' if your decimal point doesn't exist or isn't connected Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros, disableDecPoint); Display.setBrightness(100); dht.begin(); pinMode(ledPin, OUTPUT); // PIN 13 lampeggio : pinMode(A2, INPUT); // input DHT22 } void loop() { char mychar[ ] = "ORA"; float hu = dht.readHumidity(); float t = dht.readTemperature(); float orario = Time;

String e = String (mychar); //memorizza mychar String f = e.substring (0,4); //memorizza cifra a 4 digit f.toCharArray(text[1],5); //visualizza come 1 (ARRAY)

orario=orario*10; String c = String (orario); String d = c.substring (0,4); d.toCharArray(text[2],5);

//memorizza ora //memorizza cifra a 4 digit //visualizza come 2 (ARRAY)

t=t*10; String k = String(t); //memorizza t String r = k.substring (0,3)+"*"; //memorizza cifra a 3 digit + C r.toCharArray(text[3],5); //visualizza come 3 (ARRAY)

hu=hu*10; String A = String(hu); //memorizza hu String B = A.substring(0,3)+"h"; //memorizza cifra a 3 digit B.toCharArray(text[4],5); // visualizza come 4 (ARRAY) switch (i) { case 1:

digitalWrite(ledPin, LOW); //pin 13 on Humid break; case 2: digitalWrite(ledPin, HIGH); //pin 13 off ORA break; case 3: digitalWrite(ledPin, LOW); //orario Display.setNumber(Time); if (digitalRead(hrs_btn) == LOW){goto X;} if (digitalRead(min_btn) == LOW){goto X;} break; case 4: digitalWrite(ledPin, LOW); //gradi break; } if (millis() > (timer + 6000)) //tempo di visualizzazione { switch(i); Display.setChars(text[i]); i++; if (i >= 5) i = 1; // (ARRAY)conta fino a 5 poi torna a 1 timer = millis();} //--------------------------------OROLOGIO X: currentMillis = millis(); if (currentMillis - startMillis >= period) { Sec = Sec + 1; startMillis = currentMillis; } led_currentMillis = millis(); if (led_currentMillis - led_startMillis >= led_period) { led_startMillis = led_currentMillis; if (ledState == LOW) { ledState = HIGH; if (digitalRead(hrs_btn) == LOW) //avanzamento ore { Hrs = Hrs + 1; } if (digitalRead(min_btn) == LOW) //avanzamento min { Min = Min + 1; Sec = 0; } } else { ledState = LOW; } digitalWrite(ledPin, ledState);

} if (Sec == 60) { Sec = 0; Min = Min + 1; } if (Min == 60) { Min = 0; Hrs = Hrs + 1; } if (Hrs == 24) //12/24 ore { Hrs = 0; } Time = Hrs * 100 + Min; Display.refreshDisplay(); }

87) Interface I2C 16X2 LCD with Arduino

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

1

×

1

Male/Female Jumper Wires

I2C Serial Adapter

APPS AND ONLINE SERVICES Arduino Web Editor

ABOUT THIS PROJECT Interface I2C 16x2 LCD with Arduino Uno In this article I am going to interface a 16x2 I2C LCD with Arduino Uno. In my previous article is discuss about interfacing of 16x2 LCD with Arduino Uno. The difference is in number of wires. There we need more than 12 wires. But here only use just 4 wires. How ?!!!!!! Before I use parallel communication method for interfacing LCD with Arduino. But now I am using I2C Communication. How it works ? Here I use the same 16X2 LCD in my previous article. But additionally attach a I2C Module to the 16x2 LCD. It work as an inter mediator between the LCD and MCU (here Arduino). Before starting you must know about I2C Serial Interface Adapter (I2C Module) , I2C communication , and Addressof I2C LCD I2C Communication

I2C Communication I2C is short for Inter-IC. And it is a type of BUS. This is designed by Philips semiconductors. I2C is a synchronous, multi slave, multi master packet switched, single-ended serial bus. ie. multiple chips can be connect to the same bus.I2C uses only two bidirectional open collector or open drain lines, Serial Data Line (SDA) and Serial Clock Line (SCL), pulled up with resistors. Typical voltages used are +5 V or +3.3 V, although systems with other voltages are permitted. For more about I2C protocol click here. I2C Serial Interface Adapter

I2C Serial interface Adapter It is also known as I2C Module. It has total of 20 male pins. 16 pins are faced to rear side and 4 pins faced towards front side. The 16 pins for connect to 16x2 LCD and the 2 pins out of 4 pins are SDA and SCL. SDA is the serial data pin and SCL is the clock pin. The rest 2 pins for power supply (Vcc and ground).There is a POT on the I2C Module. We can control the contrast of the LCD display by rotating this POT. And there is a jumber fixed on the module. When we remove the jumber, the backlight of the LCD display will go OFF.

Address of I2C LCD Before starting we need to know about addressing of I2C devices. Every device which can attached to MCU have an address. We need to know this address for communicate with that particular device. You can see three solder pads on the I2C module. which is labeled as A0, A1 and A2. This is Address selectors. ie, each solder pads have one upper potion and a one lower potion. if, there is a connection between upper potion with lower connection it is called "Connected" otherwise it is called "Not connected". When A0, A1, A2 are in "Not Connected" condition ( A0 = 0, A1 = 0, A2 = 0) the address would be 0x27. In default the A0, A1, A2 are in "Not connected" condition. And some time default address is 0x3F. There is no need to change the address of the I2C module when we use only one LCD. But when we use more than one LCD, need to change the address. Because two or more different device can't communicate with the same address. For more address see the table given below.

Step -1 Skip this Step - 1 & Step -2 if you already know the address of the LCD In some cases A0, A1, A2 are "Not connected" state, but the address is not 0x27. We can't communicate with this address. So we need to find the original address of that device. For that we need to run the Arduino with "I2C Scanner" code. I2C Scanner Code I2C Scanner code is used for find the number of I2C devices and address of I2C devices. First add the header file for include "Wire.h" library. Then in setup part, begin the "Wire" library by "Wire.begin()". Then begin the serial monitor as the baud rate of 9600 by "Serial.begin()". Next in loop part, define two variables with the datatype "byte" named "error" and "address". Then define another variable with the "Integer ( int)" datatype named as "Devices". And set initial value as 0. Next start a for loop with minimum value of 1 and maximum of 127. "address" used as loop variable. Next input the address to wire with the function "Wire.beginTransmission()". The i2c_scanner uses the return value of the "Write.endTransmisstion()" to see if a device did acknowledge to the address. This return value store the value to the variable "error". The return value become 0, if a device acknowledge to the address. Otherwise, the return value become 4. Next use a if. And the condition is "error==0". Then print the particular address to the serial monitor only if the address1. Screwdrivers> 2. Hammer 3. Pliers 4. Flush cutter 5. Wire Stripper 6. Soldering Iron 7. Soldering Iron Stand

8. Solder 9. De-soldering pump 10. Digital Multimeter 11. Double Sided Glue Tape. 12. Nails and adhesive 13. Screws & Nuts 14. M4 Bolts x 20mm 15. Copper spacers ( To fix the Arduino Board) 16. Nylon Cable Tie Belt 17. Stainless steel angle brackets 18. 3" Rubber Caster Wheels 19. Paint brush 20. Circular saw 21 Table saw 22. Jig Saw 23. Drill and bits 24. Laser cutter 25. CNC 26. Wood files 27. Sand paper 28. Air compressor with nail gun Electronics:>1. Arduino UNO 2. 1Sheeld 3. Power Supply 12V/ 5A 4. Fan 12v 5. LED strips 6. Bush button 7. Android Smart Phone 8. Relay module 5V Step 2: Building The Machine Frame https://www.youtube.com/embed/Eu4tEww3dzw?feature=oembed

1. We used the pine wood to build the machine's frame then we used MDF sheets to cover the machine's frame, we used nails and screws to fix the MDF sheets to cover the machine's frame.Machine's dimensions is : 170 * 100 * 80 cm 2. We used aluminum sections to create the machine's door and we covered it using MDF sheets. we used laser cutter machine to cut the machine's door. 3. We used 3 hinges(L3899-2B) to fix the machine's door to the machine's body. 4. We used 4 x 3" Rubber Caster Wheels to make it movable. 5. We added a lock to secure the machine. 6. Then we started to prepare the machine for painting, we can't paint

MDF directly you should coat the machine with primer then we used black paint for the final layer. 7. After the machine has dried we used the designed stickers to give the machine the final finish and we used aluminum angels in the corners to support the machine and protect the stickers. Step 3: The Machine's Exterior Design

We used some Islamic patterns such as the Islamic star pattern to design the exterior stickers for the machine, you can download the design files and translate it into your language and we will be happy if you shared your design with us. Step 4: Electronics & Control System

Simply, the machine will sense if you donated with something and will ask you if you want to share your photo on the machine's Twitter account to encourage your friends to donate and know more about the machine. Also when filled the machine will send a SMS message to a charity association representative to ask him to empties the machine. Q: How the machine will sense if i donated with something?A: Using the first ultrasonic sensor fixed above the machine's door.Q: How the machine will interact with me ?A: Using Text to Speech Shield in 1Sheeld App, you need to write some statements at the Arduino sketch such as : TextToSpeech.say("Please stand in front of the camera After Your donation");
OneSheeld.delay(5500); TextToSpeech.say("If you want to share you photo with community please long press the Bush button"); OneSheeld.delay(7500); Q: How the machine will sense it was filled? A: I fixed two ultrasonic sensors in the internal top side of the machine, if the two sensor's values are less than 40 cm this means that the

machine was filled so it will send a SMS message to a charity association representative to ask him to empties the machine. Q: How the machine will send a SMS message? A: Using SMS Shield in 1Sheeld App, all you need yo do is to write the message body and the mobile number.SMS.send("123456789", "Message body"); Q: What should i do to let the machine take a photo for me and share it on it's Twitter account? A: The machine will ask you to press a bush button to take the photo, then the LED strips will toggle 3 times to give you the chance to say cheese :D, then it will upload the photo to its Twitter account. SCHEMATICS

CODE #define CUSTOM_SETTINGS #define INCLUDE_TERMINAL_SHIELD #define INCLUDE_SMS_SHIELD #define INCLUDE_TWITTER_SHIELD #define INCLUDE_CAMERA_SHIELD #define INCLUDE_TEXT_TO_SPEECH_SHIELD // Include 1Sheeld library. #include const int trigPin1 = 2; const int echoPin1 = 3; const int trigPin2 = 7; const int echoPin2 = 8; // Define a boolean flag. boolean isMessageSent = false; const int buttonPin = 12; // the number of the pushbutton pin int buttonState = 0; // variable for reading the pushbutton status const int ledPin = 13;

// the number of the led pin

//-------------------------------------------------------------------------------------void setup() { // Start communication OneSheeld.begin(); // initialize the LED pin as an output: pinMode(ledPin, OUTPUT);

// initialize the pushbutton pin as an input: pinMode(buttonPin, INPUT); pinMode(trigPin1, OUTPUT); pinMode(echoPin1, INPUT); pinMode(echoPin2, INPUT); pinMode(trigPin2, OUTPUT); } void loop() { long duration1, distance1, duration2, distance2; digitalWrite(trigPin1, LOW); delayMicroseconds(2); digitalWrite(trigPin1, HIGH); delayMicroseconds(10); digitalWrite(trigPin1, LOW); duration1 = pulseIn(echoPin1, HIGH); // convert the time into a distance1 distance1 = duration1 / 29 / 2; digitalWrite(trigPin2, LOW); delayMicroseconds(2); digitalWrite(trigPin2, HIGH); delayMicroseconds(10); digitalWrite(trigPin2, LOW); duration2 = pulseIn(echoPin2, HIGH); distance2 = duration2 / 29 / 2; Terminal.print("Ultrasonic1 = "); Terminal.print(distance1); Terminal.println(" cm"); Terminal.print("Ultrasonic2 = "); Terminal.print(distance2); Terminal.println(" cm"); // Ultrasonic sensor measeures the depth of the machine if this distance1 increased above 100 cm this means that the door is opened // The machine will tell the user to stand in front of the camera then the machine will take a photo for him and uplaoad it on twitter

if (distance1 < 40) { // ------------------------- Chack if the machine is filled -------------------------------if (distance1 Heller

int kontrastPIN = 9;

// Kontrast PIN

int kontrastWert = 49;

// Kontrast Wert = Kleiner => mehr Kontrast

int analogWert; // Setup der LCD Bibliothek LiquidCrystal lcd(12, 11, 5, 4, 3, 2); void setup() { // Computer Schnittstellen-Verbindung Serial.begin(9600); // Setup der PINs pinMode(hintergrundLichtPIN, OUTPUT); pinMode(kontrastPIN, OUTPUT); // Kontrast und Hintergrund Steuerung des LCD analogWrite(hintergrundLichtPIN, hintergrundLichtWert); analogWrite(kontrastPIN, kontrastWert); // Einführung des LCD in den Microkontroller lcd.begin(16, 2); }

void loop() { // Schreiben des AnalogInputs A0 analogWert = analogRead(A0) / 100; // Wertausgabe in die Console(Debugging) Serial.print(analogWert); Serial.print("\n");

// Neue Zeile

// Sender der Information an den LCD lcd.setCursor(0, 0); lcd.print("Potentiometer"); lcd.setCursor(0, 1); lcd.print(analogWert); lcd.setCursor(2, 1); lcd.print("k"); delay(100); // Löschung des Feldes(zweite Zeile, zweite Reihe) im LCD // Sonst bleibt eine 0 stehen, wenn man auf 10k geht und wieder zurück geht lcd.setCursor(1, 1); lcd.print(" "); delay(7); }

97) Smart Home Arduino In 30 Minutes Posting in Ubidots

COMPONENTS AND SUPPLIES Arduino Mega 2560 & Genuino Mega 2560

×

1

×

1

Arduino Ehernet Shield

DHT11 Temperature & Humidity Sensor (4 pins)

×

1

×

1

×

1

×

1

×

1

PIR Motion Sensor (generic)

LED (green) Buzzer

SparkFun Breadboard Power Supply 5V/3.3V

APPS AND ONLINE SERVICES Ubidots Make your account , create 3 variables , take the data directly from your Arduino Ethernet Shield

ABOUT THIS PROJECT A few days ago , I became interested more for IoT technology and its facilities and possibilities. Thinking about it and doing intensive research on the web, I found that there were no tutorials and simple designs, anyone with little or none experience with Arduino, API, JSON, WEB SERVER and a plurality of expertise could enjoy this feature ( IoT ). This publication is simple to send variables sensors to clound ( Ubidots ) in a fast , direct and dynamic way. I will not describe in this tutorial step by step account setup , since the material of their own website is much better than what I could do. www.ubidots.com

Sensor 1 - DHT11 Will need only one sensor, in my case I used a DHT11 sensor, but the Internet has several ways to make a transistor pick up ambient temperature information. Well, comments of the DHT11 sensor is a device that collects temperature and humidity environment, almost everyone who bought a starter kit have this sensor. This sensor has three terminals, one VCC to left, another in the center OUT(Data Signal) and GND (ground) right. Identified there in your component?

We need to connect it to breadboard it will connect to other more on sensor, you can follow the example we went through, so the wiring diagram had been clearer. After that, we will connect the breadboard to Arduino, in my case I used the MEGA 2560, but nothing prevents you to use any model you have, because we use the total project only 3 Digital pins and 1 Analog pin. Again nothing prevents you to modify and test in your project, for to understand better, but do it after mounting the way they explain, it will be easier after work, going for me. Once connected to the terminals VCC and GND, the OUT (Data Signal) pin plug in the Digital pin 3 of your Arduino.

Ready your sensor DHT is already positioned. Sensor 2 - PIR DYP-M003 Let's go to another sensor, in my case I used a PIR sensor DYP-ME003 (Motion Sensor), this consists of three terminals, see the image, and the terminal left VCC (5V-12V), the central OUT and the right terminal GND (ground) .

Once identified terminals, connect them to breadboard, terminal OUT at pin A1 (Analog 1) of the Arduino. The approach to the regulation of sensitivity and activation time, I'll leave as homework for you search the internet, material widely publicized in search websites. Now that the sensors are positioned and properly connected, let the

final part of the physical links of the project. Others - LED (green) The design of the LED can be both appearing on pin 13 of the Arduino and an external LED, I opted for external LED only as a way to better display the drive motion sensor PIR DYP-M003.

Note that the scheme used, connect the cathode on GND (ground) and the anode in a 220 ohm resistor, +/- 5% and turn it to the Arduino pin 4. We're almost there , the timer tah running there? Others - Buzzer The final link is the simplest , used a buzzer , which is triggered when the PIR sensor recognizes movement in the environment , therefore, beyond the LED warn visually , have a buzz that warns the presence of movement, this can be used to control access or as a primitive alarm, giving the idea of how to integrate all these features at once .

The buzzer has a positive pole , which usually in addition to their greater attachment terminal, a markup on top ( +) indicating the same and a negative pole, usually a lower leg GND (ground ) . The connection is simple, the lower leg binds to the GND (ground ), and the greater leg (+) in Arduino pin 2 . Ready, is mounted all the physical part of your Smart Home Mini system , now let's make the magic happen. Download the available code , open the Arduino IDE and upload it to your Arduino and see the operation . Remember that to send the data from the sensors , need to set in your account Ubidots the variables will be three variables , humidity , temperature and movement , once you have the data of these variables

add fields the indicated code , set data LOCAL NETWORK of its Ethernet Shield and see how simple it is .

Example DashBoar Ubidots - Collecting Data's Take the opportunity to study the code, thus understood better than the coding is simple, so you could play with it !

SCHEMATICS

CODE

#include #include #include #include // assign a MAC address for the ethernet controller. // fill in your address here: byte mac[] = { 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ // Change all ZZ MAC ADDRESS ETHERNET SHIELD }; // fill in an available IP address on your network here, // for manual configuration: IPAddress ip(0, 0, 0, 0); ETHERNET SHIELDIP ADDRESS LOCAL LAN // fill in your Domain Name Server address here: IPAddress myDns(0, 0, 0, 0); DNS IP ADDRESS LOCAL LAN // initialize the library instance: EthernetClient client; String idvariable = ""; //Varible Temperature UBIDOTS String idvariable_umidade = ""; //Variable Humidity UBIDOTS String idvariable_sensorPIR = ""; //Variable presence sensor UBIDOTS String token = ""; //TOKEN UBIDOTS //Define PIN do Sensor #define DHTPIN A1 // pino que estamos conectado #define DHTTYPE DHT11 // DHT 11 // Conecte pino 1 do sensor (esquerda) ao +5V // Conecte pino 2 do sensor ao pino de dados definido em seu Arduino // Conecte pino 4 do sensor ao GND // Conecte o resistor de 10K entre pin 2 (dados) // e ao pino 1 (VCC) do sensor DHT dht(DHTPIN, DHTTYPE); //SD Card File dataFiles;

//Declarao das variveis referentes aos pinos digitais - ALARME + PIR. int pinBuzzer = 2; int pinSensorPIR = 3; int pinLed = 4; int valorSensorPIR = 0; void setup() {

// start serial port: Serial.begin(9600); // start the Ethernet connection using a fixed IP address and DNS server: Ethernet.begin(mac, ip, myDns); // print the Ethernet board/shield's IP address: Serial.print("Conexao com a REDE LOCAL - IP: "); Serial.println(Ethernet.localIP()); delay(1000); if (Ethernet.begin(mac) == 0) { Serial.println("Falha na Conexao com a REDE Local"); // no point in carrying on, so do nothing forevermore: for(;;); } // SD Card - Iniciando Serial.println("Inicializando SD card..."); if (!SD.begin(4)) { Serial.println("Falha na Inicializacao do SD Card!"); Serial.println("Falha no Modo DATA LOGGER SD Card!"); return; } Serial.println("Inicializacao Completa"); Serial.println("Modo DATA LOGGER Inicializado com Sucesso"); // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. dataFiles = SD.open("test.txt", FILE_WRITE); // if the file opened okay, write to it: if (dataFiles) { Serial.print("Escrevendo no Arquivo test.txt..."); dataFiles.println("Testando 1, 2, 3."); // close the file:

dataFiles.close(); Serial.println("Escrita FInalizada com Sucesso"); } else { // if the file didn't open, print an error: Serial.println("Erro Abrindo arquivo test.txt"); } // re-open the file for reading: dataFiles = SD.open("test.txt"); if (dataFiles) { Serial.println("test.txt:"); // read from the file until there's nothing else in it: while (dataFiles.available()) { Serial.write(dataFiles.read()); } // close the file: dataFiles.close(); } else { // if the file didn't open, print an error: Serial.println("Erro Abrindo arquivo test.txt para LEITURA"); }

//Inicia Sensor DHT Serial.println("Iniciando - Sensor - DHT"); dht.begin(); //Definido pinos como de entrada ou de sada pinMode(pinBuzzer, OUTPUT); pinMode(pinSensorPIR, INPUT); pinMode(pinLed, OUTPUT); } void loop() {

// A leitura da temperatura e umidade pode levar 250ms! // O atraso do sensor pode chegar a 2 segundos. float h = dht.readHumidity(); float t = dht.readTemperature(); // testa se retorno valido, caso contrrio algo est errado. if (isnan(t) || isnan(h)) {

Serial.println("Falha na Leitura do Sensor - DHT"); } else { //Lendo o valor do sensor PIR. Este sensor pode assumir 2 valores //1 quando detecta algum movimento e 0 quando no detecta. valorSensorPIR = digitalRead(pinSensorPIR); Serial.print("Sensor de Movimento - Valor Recebido: "); Serial.println(valorSensorPIR); //Verificando se ocorreu deteco de movimentos if (valorSensorPIR == 1) { ligarAlarme(); } else { desligarAlarme(); }

int value_temperatura = t; int value_umidade = h; int value_sensorPIR = valorSensorPIR; save_value(String(value_temperatura)); save_value_umidade(String(value_umidade)); save_value_sensorPIR(String(value_sensorPIR)); } }

//Grava Dados Variavel 1 - Temperatura void save_value(String value_temperatura) { // if you get a connection, report back via serial: int num=0; String var = "{\"value\":"+ String(value_temperatura) + "}"; num = var.length(); delay(500); if(client.connect("things.ubidots.com", 80)) { Serial.println("connected"); // New lines according to ubidots support: //Temperatura client.println("POST /api/v1.6/variables/"+idvariable+"/values HTTP/1.1"); Serial.println("POST /api/v1.6/variables/"+idvariable+"/values HTTP/1.1"); client.println("Content-Type: application/json");

Serial.println("Content-Type: application/json"); client.println("Content-Length: "+String(num)); Serial.println("Content-Length: "+String(num)); client.println("X-Auth-Token: "+token); Serial.println("X-Auth-Token: "+token); client.println("Host: things.ubidots.com\n"); Serial.println("Host: things.ubidots.com\n"); client.print(var); Serial.print(var+"\n"); } else { // if you didn't get a connection to the server: Serial.println("Falha na Gravacao - Variavel 2 - Temperatura"); } if (!client.connected()) { Serial.println(); Serial.println("DESCONECTANDO..."); client.stop(); } if (client.available()) { char c = client.read(); Serial.print(c); } client.flush(); client.stop(); } //Grava DAdos Variavel 2 - Humidade void save_value_umidade(String value_umidade) { // if you get a connection, report back via serial: int num=0; String var2 = "{\"value\":"+ String(value_umidade) + "}"; num = var2.length(); delay(1000); if(client.connect("things.ubidots.com", 80)) { Serial.println("connected"); // New lines according to ubidots support:

//Temperatura client.println("POST /api/v1.6/variables/"+idvariable_umidade+"/values HTTP/1.1"); Serial.println("POST /api/v1.6/variables/"+idvariable_umidade+"/values HTTP/1.1"); client.println("Content-Type: application/json"); Serial.println("Content-Type: application/json"); client.println("Content-Length: "+String(num)); Serial.println("Content-Length: "+String(num)); client.println("X-Auth-Token: "+token); Serial.println("X-Auth-Token: "+token); client.println("Host: things.ubidots.com\n"); Serial.println("Host: things.ubidots.com\n"); client.print(var2); Serial.print(var2+"\n"); } else { // if you didn't get a connection to the server: Serial.println("Falha na Gravacao - Variavel 1 - Humidade"); } if (!client.connected()) { Serial.println(); Serial.println("DESCONECTANDO..."); client.stop(); } if (client.available()) { char c = client.read(); Serial.print(c); } client.flush(); client.stop(); }

//Grava Dados Variavel 3 - Sensor PIR void save_value_sensorPIR(String value_sensorPIR) { // if you get a connection, report back via serial: int num=0; String var3 = "{\"value\":"+ String(value_sensorPIR) + "}";

num = var3.length(); delay(1000); if(client.connect("things.ubidots.com", 80)) { Serial.println("connected"); // New lines according to ubidots support: //Temperatura client.println("POST /api/v1.6/variables/"+idvariable_sensorPIR+"/values HTTP/1.1"); Serial.println("POST /api/v1.6/variables/"+idvariable_sensorPIR+"/values HTTP/1.1"); client.println("Content-Type: application/json"); Serial.println("Content-Type: application/json"); client.println("Content-Length: "+String(num)); Serial.println("Content-Length: "+String(num)); client.println("X-Auth-Token: "+token); Serial.println("X-Auth-Token: "+token); client.println("Host: things.ubidots.com\n"); Serial.println("Host: things.ubidots.com\n"); client.print(var3); Serial.print(var3+"\n"); } else { // if you didn't get a connection to the server: Serial.println("Falha na Gravacao - Variavel 1 - Humidade"); } if (!client.connected()) { Serial.println(); Serial.println("DESCONECTANDO..."); client.stop(); } if (client.available()) { char c = client.read(); Serial.print(c); } client.flush(); client.stop(); }

//Alarme de Presena void ligarAlarme() { //Ligando o led digitalWrite(pinLed, HIGH); //Ligando o buzzer com uma frequencia de 1500 hz. tone(pinBuzzer, 1500); delay(4000); //tempo que o led fica acesso e o buzzer toca if (valorSensorPIR != 1){ desligarAlarme(); } } void desligarAlarme() { //Desligando o led digitalWrite(pinLed, LOW); //Desligando o buzzer noTone(pinBuzzer); }

98) Arduino Multi Functional Clock

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO We do not recommend using the Arduino UNO! It has insufficient onboard storage. We planned on using the Arduino 101 instead, but it is incompatible with the Sparkfun Color LCD Shield we use.

×

1

Arduino Wifi Shield 101 We used an older version of this shield, not the 101.

×

1

×

1

×

1

×

1

×

1

TP-LINK M5250 3G Mobile Wi-Fi AllThingsTalk IOTOPIA Rapid Development kit Grove Air Quality Sensor, Grove Buzzer, Grove Base Shield Sparkfun Color LCD Shield Sparkfun Real Time Clock Module

NECESSARY TOOLS AND MACHINES 3D - Printer

APPS AND ONLINE SERVICES Temboo

Arduino IDE

PowToon

ABOUT THIS PROJECT Introduction We’ve all had this happen before: You go to a party, stay up late… and forget to set your alarm. It’s raining, or it’s freezing and snowing the next morning and you end up being late at work or school… again. These are the sort of situations we want to prevent. We mainly designed the MultiFunctional Clock to do just that. The alarm checks your digital calendar, theweather and the traffic in your region. By doing so, it determines when youshould wake up by itself. Every day when you wake up, it will also suggest whenyou should go to bed. The MFC will also determine the optimal means oftransport. In addition, the MFC also checks the air quality in your room. You don't want to wake up feeling sick, do you? What we want to Do As you can imagine, and have read, there are a lot of things that can

interact with the MFC. Here you have a diagram:

Example situation: It's raining heavily, winds from the North. Today you have to work at 9:30 AM, tomorrow at 9:00 AM. You prefer going by bicycle, and you live more than 10 km away. In general, you take 40 minutes to prepare yourself. It's raining, more people will go to their jobs and school by bus, train and car. If you yourself are still going by bicycle or on foot, this won't affect you very much, but the opposite is true because of the wind... You'll probably get slowed down a lot either way! Let's say that you have to be woken up 10 minutes earlier than normal:

8:20 AM How we do It Here you can see how to configure the MFC. (Sorry for the bad quality!) Currently, you don't see the completed version of the code in the video. That is because we ran into difficulties quite a lot while making it. The Arduino UNO we were using did not have sufficient PROGMEM and RAM for the code. If you try to reproduce, we recommend you use any board with the same size as the UNO, but with more storage. Also use a more modern LCD TFT Shield than we did. The program will ask you the following things: How long do you usually take to get ready? (In minutes) What means of transport do you use? (Walk / Bicycle / Car) Examples of questions that could be added in the future are: What's the name of your google calendar? Where do you live? Where do you work? Do you want to use the snooze function? How long in between? (In minutes) Leave the screen on at all times? The list goes on and on! The answers could be saved in the EEPROM of the Arduino, so you don't need to answer them twice! When you answered the questions successfully, it will authenticate with google. Go to the link (provided in the serial monitor) with your favorite browser. Click on 'Allow'. Now the MFC is connected to your google account, which allows it you check your calendar. We expect that the first event in your calendar is 'going to work or school'. You will be woken up with time to completely prepare yourself in the morning, and be on time, of course. Your calendar gets checked every 5 minutes, so don't you worry about missing a newly made appointment. Air Quality

In the images below, you can see the air qualities (top left of the screen). It can detect 4 grades. "Goed" / "Good": No worries, you'll sleep well. "Aanvaardbaar" / "Acceptable": Could be better... "Slecht" / "Bad": You should open your window... "Leef je nog?!" / "How are you still alive?!": No explanation needed... An alarm goes off when the grade gets worse than "Aanvaardbaar" / "Acceptable". The sound gets louder when the quality degrades.

"Good"

"Acceptable"

"Bad"

SCHEMATICS

CODE MFC - Air qualityArduino This code gives a representation of how the air quality and time can be displayed. This code in combination with 'MFC- Alarm' code is our finished program. //-----------------RTC----------------------------// #include #include "RTClib.h" #if defined(ARDUINO_ARCH_SAMD) // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! #define Serial SerialUSB #endif RTC_DS1307 rtc; char daysOfTheWeek[7][12] = {"Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"}; char daysOfTheWeekShort[7][3] = {"Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za"}; enum Dagen { Zondag, Maandag, Dinsdag, Woensdag, Donderdag, Vrijdag, Zaterdag }; char scherm_bitbuffer[133]; //-----------------LCD----------------------------// #include #define BACKGROUND WHITE // Achtergrond #define COLOR BLACK // This is the color of the clock face, and digital clock #define COLOR_2 BLUE LCDShield lcd;

char Uur[3]; char Minuten[3]; char Seconden[3]; char Dag[3]; char Maand[3]; char Jaar[3]; char Tijd_Nu[9]; char Tijd_alarm[6]; //-----------------AirQuality---------------------// #include"AirQuality.h" #include"Arduino.h" AirQuality airqualitysensor; int current_quality =-1; //-------------------------------------------------------------------------------------// void setup () { pinMode(3, OUTPUT); analogWrite(3, 0); //-----------------instellingen scherm -----------// lcd.init(PHILIPS); lcd.contrast(50); lcd.clear(BACKGROUND); //-----------------instellingen airquality -------// Serial.begin(9600); airqualitysensor.init(14); //-----------------RTC----------------------------// #ifndef ESP8266 while (!Serial); #endif Serial.begin(9600); if (! rtc.begin()) { Serial.println("Couldn't find RTC "); lcd.setStr("Couldn't find RTC ", 20, 10, COLOR, BACKGROUND); while (1); } if (! rtc.isrunning()) { Serial.println("RTC is NOT running!"); lcd.setStr("RTC werkt niet! ", 20, 10, COLOR_2, BACKGROUND);

// following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // This line sets the RTC with an explicit date & time, for example to set // January 21, 2014 at 3am you would call: // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); } } //-------------------------------------------------------------------------------------// void loop () {

DateTime now = rtc.now(); //-----------------RTC- LCD shield----------------// //tijd.

lcd.setStr(itoa(now.hour(), Uur, 10), 45, 10, COLOR, BACKGROUND); lcd.setStr(":", 44, 26, COLOR, BACKGROUND); lcd.setStr(itoa(now.minute(), Minuten, 10), 45, 33, COLOR, BACKGROUND); lcd.setStr(":", 44, 49, COLOR, BACKGROUND); lcd.setStr(itoa(now.second(), Seconden, 10), 45, 56, COLOR, BACKGROUND); //weekdag. lcd.setStr(daysOfTheWeek[now.dayOfTheWeek()], 70, 10, COLOR, BACKGROUND); //datum. lcd.setStr(itoa(now.day(), Dag, 10), 103, 10, COLOR, BACKGROUND); lcd.setStr("/", 101 , 28, COLOR, BACKGROUND); lcd.setStr(itoa(now.month(), Maand, 10), 103, 37, COLOR, BACKGROUND); lcd.setStr("/", 101, 55, COLOR, BACKGROUND); lcd.setStr(itoa(now.year(), Jaar, 10), 103, 61, COLOR, BACKGROUND);

delay(500); //-----------------airquality---------------------// current_quality=airqualitysensor.slope(); if (current_quality >= 0) // if a valid data returned. { if (current_quality==0) { lcd.setStr("Leef je nog?! ", 5, 5, COLOR, BACKGROUND); analogWrite(3, 20); }

else if (current_quality==1) { lcd.setStr("Slecht ", 5, 5, COLOR, BACKGROUND); analogWrite(3, 20); } else if (current_quality==2) { lcd.setStr("Aanvaardbaar ", 5, 5, COLOR, BACKGROUND); analogWrite(3, 0); } else if (current_quality ==3){ lcd.setStr("Goed ", 5, 5, COLOR, BACKGROUND); analogWrite(3, 0); } } } ISR(TIMER1_OVF_vect) { if(airqualitysensor.counter==61)//set 2 seconds as a detected duty { airqualitysensor.last_vol=airqualitysensor.first_vol; airqualitysensor.first_vol=analogRead(A0); airqualitysensor.counter=0; airqualitysensor.timer_index=1; PORTB=PORTB^0x20; } else { airqualitysensor.counter++; }

}

MFC - AlarmArduino This code gives a representation of how the prog will work and how your calendar is read. This code in combination with 'MFC - Air quality' code is our finished program. #include #include

#include #include #include #include #include "RTClib.h" // #include "SparkFunColorLCDShield.h" ////////////////////////////////////////////////////////////////////////////// char cBuffer_s_0[5]; char cBuffer_s_1[5]; char cBuffer_s_2[34]; char cBuffer_s_3[24]; char cBuffer_s_4[24]; char cBuffer_s_5[24]; char cBuffer_l_0[42]; char cBuffer_l_1[56]; char* cBuffer[8] = { cBuffer_s_0, cBuffer_s_1, cBuffer_s_2, cBuffer_s_3, cBuffer_s_4, cBuffer_s_5, cBuffer_l_0, cBuffer_l_1 }; String sBuffer; String CallbackID; String AccessToken; DateTime* AccessToken_Time; String RefreshToken; String CalendarID; DateTime* ReadCalendar_Time; int Count; bool Setup; int MFC_WifiStatus; WiFiClient MFC_WifiClient(255); RTC_DS1307 MFC_Time;

DateTime* Now_Time; // LCDShield MFC_LCDColorShield; //////////////////////////////////////////////////////////////////////////////// const PROGMEM char PROGMEMTEXT_COMMON_OK[] = "OK\0"; const PROGMEM char PROGMEMTEXT_COMMON_FAIL[] = "FAIL\0"; const PROGMEM char PROGMEMTEXT_COMMON_ADJUSTED[] = "ADJUSTED\0"; const PROGMEM char PROGMEMTEXT_COMMON_UNEXPECTEDERROR[] = " [ERROR]\0"; const PROGMEM char PROGMEMTEXT_COMMON_DAYSOFTHEWEEK_OFFSET[] = "\0"; const PROGMEM char PROGMEMTEXT_COMMON_SUNDAY[] = "Sun\0"; const PROGMEM char PROGMEMTEXT_COMMON_MONDAY[] = "Mon\0"; const PROGMEM char PROGMEMTEXT_COMMON_TUESDAY[] = "Tue\0"; const PROGMEM char PROGMEMTEXT_COMMON_WEDNESDAY[] = "Wed\0"; const PROGMEM char PROGMEMTEXT_COMMON_THURSDAY[] = "Thu\0"; const PROGMEM char PROGMEMTEXT_COMMON_FRYDAY[] = "Fri\0"; const PROGMEM char PROGMEMTEXT_COMMON_SATURDAY[] = "Sat\0"; const PROGMEM char PROGMEMTEXT_COMMON_MONTHSOFTHEYEAR_OFFSET[] = "\0"; const PROGMEM char PROGMEMTEXT_COMMON_JANUARY[] = "Jan\0"; const PROGMEM char PROGMEMTEXT_COMMON_FEBRUARY[] = "Feb\0"; const PROGMEM char PROGMEMTEXT_COMMON_MARCH[] = "Mar\0"; const PROGMEM char PROGMEMTEXT_COMMON_APRIL[] = "Apr\0"; const PROGMEM char PROGMEMTEXT_COMMON_MAY[] = "May\0"; const PROGMEM char PROGMEMTEXT_COMMON_JUNE[] = "Jun\0"; const PROGMEM char PROGMEMTEXT_COMMON_JULY[] = "Jul\0"; const PROGMEM char PROGMEMTEXT_COMMON_AUGUST[] = "Aug\0"; const PROGMEM char PROGMEMTEXT_COMMON_SEPTEMBER[] = "Sept\0"; const PROGMEM char PROGMEMTEXT_COMMON_OCTOBER[] = "Oct\0"; const PROGMEM char PROGMEMTEXT_COMMON_NOVEMBER[] = "Nov\0"; const PROGMEM char PROGMEMTEXT_COMMON_DECEMBER[] = "Dec\0"; const PROGMEM char PROGMEMTEXT_COMMON_WALK[] = "Walk\0"; const PROGMEM char PROGMEMTEXT_COMMON_BICYCLE[] = "Bicycle\0"; const PROGMEM char PROGMEMTEXT_COMMON_CAR[] = "Car\0"; const PROGMEM char PROGMEMTEXT_COMMON_HTTPCODE[] = "HTTP_CODE\0"; const PROGMEM char PROGMEMTEXT_COMMON_HTTPCODESERIALPRINT[] = " HTTP_CODE: \0"; const PROGMEM char PROGMEMTEXT_COMMON_RTCDETECTION[] = "RTC DET:

\0"; const PROGMEM char PROGMEMTEXT_COMMON_RTCCONFIGURATION[] = "RTC CONF: \0"; const PROGMEM char PROGMEMTEXT_COMMON_WIFISHIELD[] = "WIFI DET: \0"; const PROGMEM char PROGMEMTEXT_COMMON_WIFICONNECTION[] = "WIFI CONN: \0"; const PROGMEM char PROGMEMTEXT_COMMON_WIFISSID[] = "MFC\0"; const PROGMEM char PROGMEMTEXT_COMMON_WIFIPASSWORD[] = "VTIV5IWMFC\0"; const PROGMEM char PROGMEMTEXT_COMMON_GOOGLEINITIALIZEOAUTH[] = "GOOGLE INITIALIZE: \0"; const PROGMEM char PROGMEMTEXT_COMMON_GOOGLEFINALIZEOAUTH[] = "GOOGLE FINALIZE: \0"; const PROGMEM char PROGMEMTEXT_COMMON_GOOGLESEARCHCALENDAR[] = "GOOGLE SEARCH CAL: \0"; const PROGMEM char PROGMEMTEXT_COMMON_GOOGLEREADCALENDAR[] = "GOOGLE READ CAL: \0"; const PROGMEM char PROGMEMTEXT_COMMON_GOOGLEDISTANCEMATRIX[] = "GOOGLE DISTANCE CALC: \0"; //////////////////////////////////////////////////////////////////////////////// const PROGMEM char PROGMEMTEXT_TEMBOO_ACCOUNT[] = "mfc\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_APPNAME[] = "MFC\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_APPKEY[] = "j4iHr8BebAHu9D1CHv4pOwGg07dyefES\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_PROFILE_INITIALIZEMFC[] = "InitializeMFC\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_PROFILE_FINALIZEMFC[] = "FinalizeMFC\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_PROFILE_SEARCHCALENDARMFC[] = "SearchCalendarMFC\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_PROFILE_READCALENDARMFC[] = "ReadCalendarMFC\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INITIALIZEOAUTH[] = "/Library/Google/OAuth/InitializeOAuth\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_FINALIZEOAUTH[] = "/Library/Google/OAuth/FinalizeOAuth\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_SEARCHCALENDARSBYNAME[] =

"/Library/Google/Calendar/SearchCalendarsByName\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_GETNEXTEVENT[] = "/Library/Google/Calendar/GetNextEvent\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_WALKINGDISTANCEMATRIX[] = "/Library/Google/DistanceMatrix/WalkingDistanceMatrix\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_BICYCLINGDISTANCEMATRIX[] = "/Library/Google/DistanceMatrix/BicyclingDistanceMatrix\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_DRIVINGDISTANCEMATRIX[] = "/Library/Google/DistanceMatrix/DrivingDistanceMatrix\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_SCOPE[] = "Scope\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_SCOPE_VALUE[] = "https://www.googleapis.com/auth/calendar\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALLBACKID[] = "CallbackID\0"; // const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALLBACKID_VALUE[] = "\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARNAME[] = "CalendarName\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARNAME_VALUE[] = "MultiFunctional Clock\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARID[] = "CalendarID\0"; // const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARID_VALUE[] = "\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ACCESSTOKEN[] = "AccessToken\0"; // const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ACCESSTOKEN_VALUE[] = "\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_REFRESHTOKEN[] = "RefreshToken\0"; // const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_REFRESHTOKEN_VALUE[] = "\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ORIGIN[] = "Origins\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ORIGIN_VALUE[] = "51.007990, 2.727744";

const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_DESTINATION[] = "Destinations\0"; const PROGMEM char PROGMEMTEXT_TEMBOO_CHOREO_INPUT_DESTINATION_VALUE[] = "51.063598, 2.666651\0"; const PROGMEM char PROGMEMTEXT[] = "\0"; //////////////////////////////////////////////////////////////////////////////// enum PROGMEMTEXT_LIST { OK, FAIL, ADJUSTED, UNEXPECTEDERROR, DAYSOFTHEWEEK_OFFSET, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRYDAY, SATURDAY, MONTHSOFTHEYEAR_OFFSET, JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER, WALK, BICYCLE, CAR, HTTP_CODE, HTTP_CODE_SERIALPRINT,

RTC_DETECTION, RTC_CONFIGURATION, WIFI_SHIELD, WIFI_CONNECTION, WIFI_SSID, WIFI_PASSWORD, GOOGLE_INITIALIZEOAUTH, GOOGLE_FINALIZEOAUTH, GOOGLE_SEARCHCALENDAR, GOOGLE_READCALENDAR, GOOGLE_DISTANCEMATRIX, ACCOUNT, APP_NAME, APP_KEY, INITIALIZEMFC, FINALIZEMFC, SEARCHCALENDARMFC, READCALENDARMFC, INITIALIZEOAUTH, FINALIZEOAUTH, SEARCHCALENDARSBYNAME, GETNEXTEVENT, WALKINGDISTANCEMATRIX, BICYCLINGDISTANCEMATRIX, DRIVINGDISTANCEMATRIX, SCOPE, SCOPE_VALUE, CALLBACKID, // CALLBACKID_VALUE, CALENDARNAME, CALENDARNAME_VALUE, CALENDARID, //CALENDARID_VALUE, ACCESSTOKEN, // ACCESSTOKEN_VALUE, REFRESHTOKEN, // REFRESHTOKEN_VALUE, ORIGIN, ORIGIN_VALUE,

DESTINATION, DESTINATION_VALUE, PROGMEMTEXT_LIST_SIZE }; PROGMEMTEXT_LIST MeansOfTransport; unsigned long UserPrepTime; unsigned long CurrentPrepTime; //////////////////////////////////////////////////////////////////////////////// const PROGMEM char* const PROGMEMTEXT_TABLE[] = { PROGMEMTEXT_COMMON_OK, PROGMEMTEXT_COMMON_FAIL, PROGMEMTEXT_COMMON_ADJUSTED, PROGMEMTEXT_COMMON_UNEXPECTEDERROR, PROGMEMTEXT_COMMON_DAYSOFTHEWEEK_OFFSET, PROGMEMTEXT_COMMON_SUNDAY, PROGMEMTEXT_COMMON_MONDAY, PROGMEMTEXT_COMMON_TUESDAY, PROGMEMTEXT_COMMON_WEDNESDAY, PROGMEMTEXT_COMMON_THURSDAY, PROGMEMTEXT_COMMON_FRYDAY, PROGMEMTEXT_COMMON_SATURDAY, PROGMEMTEXT_COMMON_MONTHSOFTHEYEAR_OFFSET, PROGMEMTEXT_COMMON_JANUARY, PROGMEMTEXT_COMMON_FEBRUARY, PROGMEMTEXT_COMMON_MARCH, PROGMEMTEXT_COMMON_APRIL, PROGMEMTEXT_COMMON_MAY, PROGMEMTEXT_COMMON_JUNE, PROGMEMTEXT_COMMON_JULY, PROGMEMTEXT_COMMON_AUGUST, PROGMEMTEXT_COMMON_SEPTEMBER, PROGMEMTEXT_COMMON_OCTOBER, PROGMEMTEXT_COMMON_NOVEMBER, PROGMEMTEXT_COMMON_DECEMBER, PROGMEMTEXT_COMMON_WALK, PROGMEMTEXT_COMMON_BICYCLE, PROGMEMTEXT_COMMON_CAR,

PROGMEMTEXT_COMMON_HTTPCODE, PROGMEMTEXT_COMMON_HTTPCODESERIALPRINT, PROGMEMTEXT_COMMON_RTCDETECTION, PROGMEMTEXT_COMMON_RTCCONFIGURATION, PROGMEMTEXT_COMMON_WIFISHIELD, PROGMEMTEXT_COMMON_WIFICONNECTION, PROGMEMTEXT_COMMON_WIFISSID, PROGMEMTEXT_COMMON_WIFIPASSWORD, PROGMEMTEXT_COMMON_GOOGLEINITIALIZEOAUTH, PROGMEMTEXT_COMMON_GOOGLEFINALIZEOAUTH, PROGMEMTEXT_COMMON_GOOGLESEARCHCALENDAR, PROGMEMTEXT_COMMON_GOOGLEREADCALENDAR, PROGMEMTEXT_COMMON_GOOGLEDISTANCEMATRIX, PROGMEMTEXT_TEMBOO_ACCOUNT, PROGMEMTEXT_TEMBOO_APPNAME, PROGMEMTEXT_TEMBOO_APPKEY, PROGMEMTEXT_TEMBOO_PROFILE_INITIALIZEMFC, PROGMEMTEXT_TEMBOO_PROFILE_FINALIZEMFC, PROGMEMTEXT_TEMBOO_PROFILE_SEARCHCALENDARMFC, PROGMEMTEXT_TEMBOO_PROFILE_READCALENDARMFC, PROGMEMTEXT_TEMBOO_CHOREO_INITIALIZEOAUTH, PROGMEMTEXT_TEMBOO_CHOREO_FINALIZEOAUTH, PROGMEMTEXT_TEMBOO_CHOREO_SEARCHCALENDARSBYNAME, PROGMEMTEXT_TEMBOO_CHOREO_GETNEXTEVENT, PROGMEMTEXT_TEMBOO_CHOREO_WALKINGDISTANCEMATRIX, PROGMEMTEXT_TEMBOO_CHOREO_BICYCLINGDISTANCEMATRIX, PROGMEMTEXT_TEMBOO_CHOREO_DRIVINGDISTANCEMATRIX, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_SCOPE, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_SCOPE_VALUE, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALLBACKID, // PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALLBACKID_VALUE, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARNAME, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARNAME_VALUE, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARID, // PROGMEMTEXT_TEMBOO_CHOREO_INPUT_CALENDARID_VALUE, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ACCESSTOKEN, // PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ACCESSTOKEN_VALUE, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_REFRESHTOKEN, // PROGMEMTEXT_TEMBOO_CHOREO_INPUT_REFRESHTOKEN_VALUE,

PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ORIGIN, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_ORIGIN_VALUE, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_DESTINATION, PROGMEMTEXT_TEMBOO_CHOREO_INPUT_DESTINATION_VALUE, PROGMEMTEXT }; #define getPROGMEMTEXT_DayOfTheWeek(DayOfTheWeek) (strcpy_P(cBuffer[0], (char*)pgm_read_word(&(PROGMEMTEXT_TABLE[DayOfTheWeek + PROGMEMTEXT_LIST::DAYSOFTHEWEEK_OFFSET + 1])))) #define getPROGMEMTEXT_MonthOfTheYear(MonthOfTheYear) (strcpy_P(cBuffer[0], (char*)pgm_read_word(&(PROGMEMTEXT_TABLE[MonthOfTheYear + PROGMEMTEXT_LIST::MONTHSOFTHEYEAR_OFFSET])))) #define getPROGMEMTEXT(enum_PROGMEMTEXT_LIST_value) (strcpy_P(cBuffer[7], (char*)pgm_read_word(& (PROGMEMTEXT_TABLE[enum_PROGMEMTEXT_LIST_value])))) #define getPROGMEMTEXT_i(enum_PROGMEMTEXT_LIST_value, cBuffer_index) (strcpy_P(cBuffer[cBuffer_index], (char*)pgm_read_word(& (PROGMEMTEXT_TABLE[enum_PROGMEMTEXT_LIST_value])))) //////////////////////////////////////////////////////////////////////////////// void setup() { Serial.begin(57600); while(!Serial); pinMode(3, OUTPUT); analogWrite(3, 0); /* MFC_LCDColorShield.init(PHILIPS); MFC_LCDColorShield.contrast(50); MFC_LCDColorShield.clear(WHITE); */ RTC(); Wifi(); } //////////////////////////////////////////////////////////////////////////////////////////////////// void loop() {

if(Setup == 0) { Serial.println(F("\nHow long do you usually take to get ready? (In minutes)")); while(!Serial.available()); sBuffer = Serial.readString(); Serial.print(sBuffer); UserPrepTime = (atol(sBuffer.c_str()) * 60); Serial.println(F("\nWhat means of transport do you use? (Walk / Bicycle / Car)")); while(!Serial.available()); sBuffer = Serial.readString(); if(sBuffer.c_str() == getPROGMEMTEXT(PROGMEMTEXT_LIST::WALK)) MeansOfTransport = PROGMEMTEXT_LIST::WALKINGDISTANCEMATRIX; else if(sBuffer.c_str() == getPROGMEMTEXT(PROGMEMTEXT_LIST::BICYCLE)) MeansOfTransport = PROGMEMTEXT_LIST::BICYCLINGDISTANCEMATRIX; else if(sBuffer.c_str() == getPROGMEMTEXT(PROGMEMTEXT_LIST::DRIVE)) MeansOfTransport = PROGMEMTEXT_LIST::DRIVINGDISTANCEMATRIX; else MeansOfTransport = PROGMEMTEXT_LIST::DRIVINGDISTANCEMATRIX; Serial.println(sBuffer); Initialize(); Finalize(); SearchCalendar(); ReadCalendar(); Setup = 1; } delete Now_Time; Now_Time = new DateTime(MFC_Time.now()); if(Now_Time->unixtime() < (ReadCalendar_Time->unixtime() - CurrentPrepTime - 300)) {

if((Count % 300) == 0) { ReadCalendar(); DistanceMatrix(); } } if(((Now_Time->unixtime() - 30UL) < (ReadCalendar_Time->unixtime() CurrentPrepTime)) && (Now_Time->unixtime() >= (ReadCalendar_Time->unixtime() CurrentPrepTime))) { analogWrite(3, 20); delay(3000UL); analogWrite(3, 0); } else if(Now_Time->unixtime() > (ReadCalendar_Time->unixtime() - CurrentPrepTime)) { ReadCalendar(); DistanceMatrix(); } Serial.print(F("Current date: ")); Serial.print(getPROGMEMTEXT_DayOfTheWeek(Now_Time->dayOfTheWeek())); Serial.print(F(" ")); Serial.print(Now_Time->day(), DEC); Serial.print(F("/")); Serial.print(Now_Time->month(), DEC); Serial.print(F(" (")); Serial.print(getPROGMEMTEXT_MonthOfTheYear(Now_Time->month())); Serial.print(F(") ")); Serial.println(Now_Time->year()); Serial.print(F("Current time: ")); Serial.print(Now_Time->hour(), DEC); Serial.print(F(":")); Serial.print(Now_Time->minute(), DEC); Serial.print(F(":")); Serial.println(Now_Time->second(), DEC); Serial.print(F("Alarm time: ")); if((ReadCalendar_Time->minute() == 0) && (CurrentPrepTime != 0)) Serial.print(ReadCalendar_Time->hour() - 1, DEC); else Serial.print(ReadCalendar_Time->hour(), DEC); Serial.print(F(":")); Serial.print(ReadCalendar_Time->minute() - CurrentPrepTime, DEC); Serial.print(F(":")); Serial.println(ReadCalendar_Time->second(), DEC);

Serial.println(); /* MFC_LCDColorShield.setStr(itoa(Now_Time->hour(), cBuffer[7], 10), 44, 10, BLACK, WHITE); MFC_LCDColorShield.setStr(":", 44, 26, BLACK, WHITE); MFC_LCDColorShield.setStr(itoa(Now_Time->minute(), cBuffer[7], 10), 44, 34, BLACK, WHITE); MFC_LCDColorShield.setStr(":", 44, 42, BLACK, WHITE); MFC_LCDColorShield.setStr(itoa(Now_Time->second(), cBuffer[7], 10), 44, 58, BLACK, WHITE); MFC_LCDColorShield.setStr(getPROGMEMTEXT_DayOfTheWeek(Now_Time>dayOfTheWeek()), 70, 10, COLOR, BACKGROUND); MFC_LCDColorShield.setStr(itoa(Now_Time->day(), Dag, 10), 70, 10, COLOR, BACKGROUND); MFC_LCDColorShieldcd.setStr("/", 101 , 28, COLOR, BACKGROUND); MFC_LCDColorShield.setStr(itoa(Now_Time->month(), Maand, 10), 103, 37, COLOR, BACKGROUND); MFC_LCDColorShield.setStr("/", 101, 55, COLOR, BACKGROUND); MFC_LCDColorShield.setStr(itoa(Now_Time->year(), Jaar, 10), 103, 61, COLOR, BACKGROUND); */ delay(1000); Count++; } //////////////////////////////////////////////////////////////////////////////// void RTC(void) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::RTC_DETECTION)); if (MFC_Time.begin()) { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); } else { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::RTC_CONFIGURATION)); if (MFC_Time.isrunning()) {

Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); } else { MFC_Time.adjust(DateTime(F(__DATE__), F(__TIME__))); Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::ADJUSTED)); } } void Wifi(void) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::WIFI_SHIELD)); if (WiFi.status() != WL_NO_SHIELD) { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); } else { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::WIFI_CONNECTION)); MFC_WifiStatus = WL_IDLE_STATUS; for(int i = 0; (i < 10) && (MFC_WifiStatus != WL_CONNECTED); i++) { MFC_WifiStatus = WiFi.begin(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::WIFI_SSID, 6), getPROGMEMTEXT_i(PROGMEMTEXT_LIST::WIFI_PASSWORD, 7)); delay(6000); } if (MFC_WifiStatus == WL_CONNECTED) { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); } else { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } } //////////////////////////////////////////////////////////////////////////////// void Initialize(void) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::GOOGLE_INITIALIZEOAUTH TembooChoreo InitializeOAuthChoreo(MFC_WifiClient); InitializeOAuthChoreo.begin();

InitializeOAuthChoreo.setAccountName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ACCOUNT 0)); InitializeOAuthChoreo.setAppKeyName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_NAME 1)); InitializeOAuthChoreo.setAppKey(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_KEY 2)); InitializeOAuthChoreo.setProfile(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::INITIALIZEMFC 3)); InitializeOAuthChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::SCOPE, 4), getPROGMEMTEXT_i(PROGMEMTEXT_LIST::SCOPE_VALUE, 6));

InitializeOAuthChoreo.setChoreo(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::INITIALIZEOAUTH 7)); if(InitializeOAuthChoreo.run() == 0) { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); while(InitializeOAuthChoreo.available()) { InitializeOAuthChoreo.readStringUntil('\x1F'); InitializeOAuthChoreo.readStringUntil('\x1E'); InitializeOAuthChoreo.readStringUntil('\x1F'); Serial.println(F("\nNavigate to this web-page and click \"Allow\".")); Serial.println(InitializeOAuthChoreo.readStringUntil('\x1E')); while(!Serial.available()); InitializeOAuthChoreo.readStringUntil('\x1F'); CallbackID = InitializeOAuthChoreo.readStringUntil('\x1E'); CallbackID.trim(); // Serial.print((char)InitializeOAuthChoreo.read()); } } else { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } InitializeOAuthChoreo.close();

} //////////////////////////////////////////////////////////////////////////////// void Finalize(void) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::GOOGLE_FINALIZEOAUTH)); TembooChoreo FinalizeOAuthChoreo(MFC_WifiClient); FinalizeOAuthChoreo.begin(); FinalizeOAuthChoreo.setAccountName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ACCOUNT 0)); FinalizeOAuthChoreo.setAppKeyName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_NAME 1)); FinalizeOAuthChoreo.setAppKey(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_KEY 2)); FinalizeOAuthChoreo.setProfile(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::FINALIZEMFC 3)); FinalizeOAuthChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::CALLBACKID 4), CallbackID); FinalizeOAuthChoreo.setChoreo(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::FINALIZEOAUTH 7)); if(FinalizeOAuthChoreo.run() == 0) { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); delete Now_Time; Now_Time = new DateTime(MFC_Time.now()); delete AccessToken_Time; AccessToken_Time = new DateTime(Now_Time->year(), Now_Time->month(), Now_Time->day(), Now_Time->hour() + 1, Now_Time->minute(), Now_Time->second()); while(FinalizeOAuthChoreo.available()) { FinalizeOAuthChoreo.readStringUntil('\x1F'); FinalizeOAuthChoreo.readStringUntil('\x1E'); FinalizeOAuthChoreo.readStringUntil('\x1F'); RefreshToken = FinalizeOAuthChoreo.readStringUntil('\x1E');

RefreshToken.trim(); FinalizeOAuthChoreo.readStringUntil('\x1F'); FinalizeOAuthChoreo.readStringUntil('\x1E'); FinalizeOAuthChoreo.readStringUntil('\x1F'); FinalizeOAuthChoreo.readStringUntil('\x1E'); FinalizeOAuthChoreo.readStringUntil('\x1F'); AccessToken = FinalizeOAuthChoreo.readStringUntil('\x1E'); AccessToken.trim(); // Serial.print((char)FinalizeOAuthChoreo.read()); } } else { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } FinalizeOAuthChoreo.close(); } //////////////////////////////////////////////////////////////////////////////// void SearchCalendar(void) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::GOOGLE_SEARCHCALENDAR TembooChoreo SearchCalendarChoreo(MFC_WifiClient); SearchCalendarChoreo.begin(); SearchCalendarChoreo.setAccountName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ACCOUNT 0)); SearchCalendarChoreo.setAppKeyName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_NAME 1)); SearchCalendarChoreo.setAppKey(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_KEY 2)); delete Now_Time; Now_Time = new DateTime(MFC_Time.now()); if(Now_Time->unixtime() < AccessToken_Time->unixtime()) { SearchCalendarChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ACCESSTOKEN

3), AccessToken); } else { delete AccessToken_Time; AccessToken_Time = new DateTime(Now_Time->year(), Now_Time->month(), Now_Time->day(), Now_Time->hour() + 1, Now_Time->minute(), Now_Time->second());

SearchCalendarChoreo.setProfile(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::SEARCHCALENDAR 3)); SearchCalendarChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::REFRESHTOKEN 4), RefreshToken); } SearchCalendarChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::CALENDARNAME 5), getPROGMEMTEXT_i(PROGMEMTEXT_LIST::CALENDARNAME_VALUE, 6));

SearchCalendarChoreo.setChoreo(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::SEARCHCALENDA 7)); if(SearchCalendarChoreo.run() == 0) { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); while(SearchCalendarChoreo.available()) { SearchCalendarChoreo.readStringUntil('\x1F'); SearchCalendarChoreo.readStringUntil('\x1E'); SearchCalendarChoreo.readStringUntil('\x1F'); SearchCalendarChoreo.readStringUntil('\x1E'); SearchCalendarChoreo.readStringUntil('\x1F'); sBuffer = SearchCalendarChoreo.readStringUntil('\x1E'); sBuffer.trim(); if(sBuffer != getPROGMEMTEXT(PROGMEMTEXT_LIST::PROGMEMTEXT_LIST_SIZE)) AccessToken = sBuffer; SearchCalendarChoreo.readStringUntil('\x1F'); SearchCalendarChoreo.readStringUntil('\x1E'); SearchCalendarChoreo.readStringUntil('\x1F'); SearchCalendarChoreo.readStringUntil('\x1E'); SearchCalendarChoreo.readStringUntil('\x1F'); CalendarID = SearchCalendarChoreo.readStringUntil('\x1E');

CalendarID.trim(); SearchCalendarChoreo.readStringUntil('\x1F'); SearchCalendarChoreo.readStringUntil('\x1E'); // Serial.print((char)SearchCalendarChoreo.read()); } } else { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } SearchCalendarChoreo.close(); } //////////////////////////////////////////////////////////////////////////////// void ReadCalendar(void) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::GOOGLE_READCALENDAR)); TembooChoreo ReadCalendarChoreo(MFC_WifiClient); ReadCalendarChoreo.begin(); ReadCalendarChoreo.setAccountName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ACCOUNT 0)); ReadCalendarChoreo.setAppKeyName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_NAME 1)); ReadCalendarChoreo.setAppKey(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_KEY 2)); delete Now_Time; Now_Time = new DateTime(MFC_Time.now()); if(Now_Time->unixtime() < AccessToken_Time->unixtime()) { ReadCalendarChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ACCESSTOKEN 3), AccessToken); } else { delete AccessToken_Time; AccessToken_Time = new DateTime(Now_Time->year(), Now_Time->month(), Now_Time->day(), Now_Time->hour() + 1, Now_Time->minute(), Now_Time->second());

ReadCalendarChoreo.setProfile(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::READCALENDARMF 3)); ReadCalendarChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::REFRESHTOKEN 4), RefreshToken); } ReadCalendarChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::CALENDARID 6), CalendarID); ReadCalendarChoreo.setChoreo(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::GETNEXTEVENT 7)); if(ReadCalendarChoreo.run() == 0) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); while(ReadCalendarChoreo.available()) { ReadCalendarChoreo.readStringUntil('\x1F'); ReadCalendarChoreo.readStringUntil('\x1E'); ReadCalendarChoreo.readStringUntil('\x1F'); ReadCalendarChoreo.readStringUntil('\x1E'); ReadCalendarChoreo.readStringUntil('\x1F'); sBuffer = ReadCalendarChoreo.readStringUntil('\x1E'); sBuffer.trim(); if(sBuffer != getPROGMEMTEXT(PROGMEMTEXT_LIST::PROGMEMTEXT_LIST_SIZE)) { sBuffer[4] = '\0'; sBuffer[7] = '\0'; sBuffer[10] = '\0'; sBuffer[13] = '\0'; sBuffer[16] = '\0'; sBuffer[19] = '\0'; delete ReadCalendar_Time; ReadCalendar_Time = new DateTime(atoi(&sBuffer[0]), atoi(&sBuffer[5]), atoi(&sBuffer[8]), atoi(&sBuffer[11]), atoi(&sBuffer[14]), atoi(&sBuffer[17])); Serial.println(); } else {

Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::UNEXPECTEDERROR)); while(true); } ReadCalendarChoreo.readStringUntil('\x1F'); sBuffer = ReadCalendarChoreo.readStringUntil('\x1E'); sBuffer.trim(); if(sBuffer != getPROGMEMTEXT(PROGMEMTEXT_LIST::PROGMEMTEXT_LIST_SIZE)) AccessToken = sBuffer; sBuffer = getPROGMEMTEXT(PROGMEMTEXT_LIST::PROGMEMTEXT_LIST_SIZE); ReadCalendarChoreo.readStringUntil('\x1F'); ReadCalendarChoreo.readStringUntil('\x1E'); ReadCalendarChoreo.readStringUntil('\x1F'); ReadCalendarChoreo.readStringUntil('\x1E'); //Serial.print((char)ReadCalendarChoreo.read()); } } else { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } ReadCalendarChoreo.close(); } //////////////////////////////////////////////////////////////////////////////// void DistanceMatrix(void) { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::GOOGLE_DISTANCEMATRIX TembooChoreo DistanceMatrixChoreo(MFC_WifiClient); DistanceMatrixChoreo.begin(); DistanceMatrixChoreo.setAccountName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ACCOUNT 0)); DistanceMatrixChoreo.setAppKeyName(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_NAME 1));

DistanceMatrixChoreo.setAppKey(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::APP_KEY 2)); DistanceMatrixChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ORIGIN 3), getPROGMEMTEXT_i(PROGMEMTEXT_LIST::ORIGIN_VALUE, 4)); DistanceMatrixChoreo.addInput(getPROGMEMTEXT_i(PROGMEMTEXT_LIST::DESTINATION 5), getPROGMEMTEXT_i(PROGMEMTEXT_LIST::DESTINATION_VALUE, 6)); DistanceMatrixChoreo.setChoreo(getPROGMEMTEXT_i(MeansOfTransport, 7)); DistanceMatrixChoreo.run(); if(DistanceMatrixChoreo.run() == 0) { Serial.println(getPROGMEMTEXT(PROGMEMTEXT_LIST::OK)); while(DistanceMatrixChoreo.available()) { DistanceMatrixChoreo.readStringUntil('\x1F'); DistanceMatrixChoreo.readStringUntil('\x1E'); DistanceMatrixChoreo.readStringUntil('\x1F'); sBuffer = DistanceMatrixChoreo.readStringUntil('\x1E'); sBuffer.trim(); CurrentPrepTime = UserPrepTime + atoi(sBuffer.c_str()); DistanceMatrixChoreo.readStringUntil('\x1F'); DistanceMatrixChoreo.readStringUntil('\x1E'); // Serial.print((char)DistanceMatrixChoreo.read()); } } else { Serial.print(getPROGMEMTEXT(PROGMEMTEXT_LIST::FAIL)); while(true); } DistanceMatrixChoreo.close(); }

99) Arduino Smart Humidifer

COMPONENTS AND SUPPLIES Basic Bread board - 16.5*5.5 cm ×

1

LCD 16*2 Characters - Green Yellow back light

×

1

Humidity /temperature sensor module

×

1

Breadboard Jumper Wire Pack(200mm/165mm/125mm/80mm) ×

1

Arduino UNO & Genuino UNO ×

1

×

1

×

1

Momentary Pushbutton Switch Grove - Water Atomization v1.0

ABOUT THIS PROJECT There are three key components to healthy air. It must be fresh, clean, and have the proper humidity. Humans are sensitive to humidity because the human body uses evaporative cooling, enabled by perspiration, as the primary mechanism to rid itself of waste heat. Humans can be comfortable within a wide range of humidity depending on the temperature—from thirty to seventy percent but ideally between 50% and 60%. Very low humidity can create discomfort, respiratory problems, and aggravate allergies in some individuals. In the winter, it is advisable to maintain relative humidity at 30 percent or above. Extremely low (below 20%) relative humidity may also cause eye irritation. Humidify your home, especially the bedrooms. Low humidity is a common cause of nosebleeds. The right humidity levels help your home to feel cool in the summer and warm in the winter.In the winter, or in regions that tend to be cold for most of the year,

humidification, or adding moisture, is essential. This project senses temperature & humidity from your room or environment and check either it is in comfortable range or not. If it finds that relative humidity is lower than the required limit, it turns on the humidifier for 10 seconds, then again checks the humidity level. If not adequate then again turns on. Seeed studio HSM-20G temperature & humidity sensor is used here to sense the temperature and humidity. A LCD display is used to show the temperature and humidity level on your room. You can use Grove button to manually control the humidifier. To control all the things Arduino UNO is used. How it works: Grove - Water Atomization is fine Grove module for you to develop an atomizer or an atomizer module in your applications easily. It Heated with ultrasound. If you give logic high to the enable pin it starts working. It works with 5V and takes maximum 2W. Details HSM-20G temperature & humidity module: HSM-20G is a low price temperature/humidity module and gives analog reading. It converts relative humidity and temperature to corresponding standard voltage Connection: Follow the schematic diagram carefully. A 10K resistor is connected to T and Ground pin according to datasheet. Another 100K and 10uF capacitor is connected to H and Ground pin. I used open source fritzing to draw the schematic. I did not find Water Atomization to fritzing parts library and for that I used Grove buzzer module and made a note as water automization. Don't panic, connection is same and just consider the signal pin as enable pin of water atomization. I attached two image here, one without LCD connection and another with LCD connection. Fritzing source file is attached to source code of my github repository. You can download it.

Collect all the component mentioned below. Connect HSM-20G temperature and humidity sensor to the arduino board with the resistors and capacitor shown in the schematic. You can use breadboard to easily connect sensor to the resistors and capacitor and the arduino board.

Make & Test: Upload the program to the arduino board and open the serial monitor. If it works correctly you should get the following result from the serial

monitor.

Now connect the LCD display to the arduino board and test it. LCD should display the relative humidity and temperature. If everything works well now it is the time to connect water atomization to the system. To do that first connect the driver board to the arduino board, then connect ultrasonic transducer to the driver board.

Take a cup filled with water and put some tissue into the water. Put ultrasonic transducer onto tissue. Note that the bottom side is the side with hollow which is supposed to face downside. Let bottom of transducer plate sink into the water and keep top side above water. The function of tissue is lead water to the transducer and keep upper side of transducer above water.

Power up the system, If you see vapor produced then congratulation! You made it, experiment with it!!! Notes that do not touch transducer interface pins directly because peak output voltage of Drier board can be 65V.

SCHEMATICS

CODE #include LiquidCrystal lcd(13, 12, 8, 9, 10, 11); const byte nsum=10; //int humidityPin=A0; //int Thgm20Pin=A1; int atomizationPin = 2; unsigned int sensorValue2 = 0; // variable to store the value coming from the sensor unsigned int sensorValue3 = 0; // variable to store the value coming from the sensor void setup() { Serial.begin(9600); pinMode(atomizationPin, OUTPUT); lcd.begin(16, 2); } void loop() { for (byte i=0;i= width) { xPos = 0; background(0); } else { // increment the horizontal position: xPos++; } } void serialEvent (Serial myPort) { // get the ASCII string:

String inString = myPort.readStringUntil('\n'); if (inString != null) { // trim off any whitespace: inString = trim(inString); // convert to an int and map to the screen height: inByte = float(inString); println(inByte); inByte = map(inByte, 0, 1023, 0, height); } } */ /* Max/MSP v5 patch for this example ----------begin_max5_patcher---------1591.3oc0YszbaaCD9r7uBL5RalQUAO3CvdyS5zVenWZxs5NcfHgjPCIfJIT RTxj+6AOHkoTDooroUs0AQPR73a+1cwtK3WtZxzEpOwqlB9YveAlL4KWMYh6 Q1GLo99ISKXeJMmU451zTUQAWpmNy+NM+SZ2y+sR1l02JuU9t0hJvFlNcMPy dOuBv.U5Rgb0LPpRpYBooM3529latArTUVvzZdFPtsXAuDrrTU.f.sBffXxL vGE50lIHkUVJXq3fRtdaoDvjYfbgjujaFJSCzq4.tLaN.bi1tJefWpqbO0uz 1IjIABoluxrJ1guxh2JfPO2B5zRNyBCLDFcqbwNvuv9fHCb8bvevyyEU2JKT

YhkBSWPAfq2TZ6YhqmuMUo0feUn+rYpY4YtY+cFw3lUJdCMYAapZqzwUHX8S crjAd+SIOU6UBAwIygy.Q1+HAA1KH6EveWOFQlitUK92ehfal9kFhUxJ3tWc sgpxadigWExbt1o7Ps5dk3yttivyg20W0VcSmg1G90qtx92rAZbH4ez.ruy1 nhmaDPidE07J+5n2sg6E6oKXxUSmc20o6E3SPRDbrkXnPGUYE.i5nCNB9TxQ

jG.G0kCTZtH88f07Rt0ZMMWUw8VvbKVAaTk6GyoraPdZff7rQTejBN54lgyv HE0Ft7AvIvvgvIwO23jBdUkYOuSvIFSiNcjFhiSsUBwsUCh1AgfNSBAeNDBZ DIDqY.f8.YjfjV1HAn9XDTxyNFYatVTkKx3kcK9GraZpI5jv7GOx+Z37Xh82

LSKHIDmDXaESoXRngIZQDKVkpxUkMCyXCQhcCK1z.G457gi3TzMz4RFD515F G3bIQQwcP3SOF0zlkGhiCBQ1kOHHFFlXaEBQIQnCwv9QF1LxPZ.A4jR5cyQs vbvHMJsLll01We+rE2LazX6zYmCraRrsPFwKg1ANBZFY.IAihr8Ox.aH0oAL hB8nQVw0FSJiZeunOykbT6t3r.NP8.iL+bnwNiXuVMNJH9H9YCm89CFXPBER bz422p8.O4dg6kRxdyjDqRwMIHTbT3QFLskxJ8tbmQK4tm0XGeZWF7wKKtYY aTAF.XPNFaaQBinQMJ4QLF0aNHF0JtYuHSxoUZfZY6.UU2ejJTb8lQw8Fo5k Rv6e2PI+fOM71o2ecY1VgTYdCSxxUqLokuYq9jYJi6lxPgD2NIPePLB0mwbG YA9Rgxdiu1k5xiLlSU6JVnx6wzg3sYHwTesB8Z5D7RiGZpXyvDNJY.DQX3.H hvmcUN4bP1yCkhpTle2P37jtBsKrLWcMScEmltOPv22ZfAqQAdKr9HzATQwZ q18PrUGt6Tst2XMCRUfGuhXs6ccn23YloomMqcTiC5iMGPsHsHRWhWFlaenV XcqwgCQiGGJzptyS2ZMODBz6fGza0bzmXBj7+DA94bvpR01MffAlueO7HwcI pWCwmzJdvi9ILgflLAFmyXB6O7ML0YbD26lenmcGxjVsZUN+A6pUK7AtTrPg M+eRYG0qD9j4I7eEbco8Xh6WcO.or9XDC6UCiewbXHkh6xm5LiPEkzpJDRTu mEB44Fgz4NCtJvX.SM1vo2SlTCZGAe7GZu6ahdRyzFOhYZ+mbVVSYptBw.K1 tboIkatIA7c1cTKD1u.honLYV04VkluHsXe0szv9pQCE9Ro3jaVB1o15pz2X zYoBvO5KXCAe0LCYJybE8ZODf4fV8t9qW0zYxq.YJfTosj1bv0xc.SaC0+AV 9V9L.KKyV3SyTcRtmzi6rO.O16USvts4B5xe9EymDvebK0eMfW6+NIsNlE2m eqRyJ0utRq13+RjmqYKN1e.4d61jjdsauXe3.2p6jgi9hsNIv97CoyJ01xzl c3ZhUCtSHx3UZgjoEJYqNY+hYs5zZQVFW19L3JDYaTlMLqAAt1G2yXlnFg9a 53L1FJVcv.cOX0dh7mCVGCLce7GFcQwDdH5Ta3nyAS0pQbHxegr+tGIZORgM RnMj5vGl1Fs16drnk7Tf1XOLgv1n0d2iEsCxR.eQsNOZ4FGF7whofgfI3kES 1kCeOX5L2rifbdu0A9ae2X.V33B1Z+.Bj1FrP5iFrCYCG5EUWSG.hhunHJd. HJ5hhnng3h9HPj4lud02.1bxGw. -----------end_max5_patcher-----------

*/

104) Robotic Arm Control Using Bluetooth Arduino and Android App

COMPONENTS AND SUPPLIES Adafruit ROBOTIC ARM ×

1

×

1

×

5

HC-05 Bluetooth Module

L293D MOTOR DRIVERS Arduino Mega 2560 & Genuino Mega 2560

×

1

×

2

×

1

×

3

DC motor (generic) BASE AS CAR CHASIS 9V battery (generic)

APPS AND ONLINE SERVICES

LOVELY ROBOTIC ARM Arduino IDE

ABOUT THIS PROJECT Operating robotic arm with wireless Bluetooth connection from Android app. Connections: Connect: pin 2,3 to wheel left motor pin 4,5 to wheel right motor pin 6,7 to gripper hand motor for holding and dropping pin 8,9 to joint 2 motor pin 10,11, to joint 3 motor

Pin 12,13 to joint 4 motor Pin 14,15 to joint 5 motor HC-05 rx to tx of Arduino HC-05 tx to rx of Arduino HC-05 vcc to 5v of Arduino HC-05 gnd to gnd of Arduino

SCHEMATICS

CODE int inByte; void setup() { Serial.begin(9600); pinMode(2, OUTPUT); pinMode(3, OUTPUT);

pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); pinMode(13, OUTPUT); pinMode(14, OUTPUT); pinMode(15, OUTPUT); } void loop() { if (Serial.available() > 0) { inByte = Serial.read(); switch (inByte) { case '1': digitalWrite(2, LOW); digitalWrite(3, HIGH); digitalWrite(4, LOW); digitalWrite(5, HIGH); Serial.println("FRONT"); break; case '2': digitalWrite(2, HIGH); digitalWrite(3, LOW); digitalWrite(4, HIGH); digitalWrite(5, LOW); Serial.println("BACK"); break; case '3': digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, LOW); digitalWrite(5, HIGH); Serial.println("LEFT"); break; case '4': digitalWrite(2, LOW); digitalWrite(3, HIGH); digitalWrite(4, LOW);

digitalWrite(5, LOW); Serial.println("RIGHT"); break; case '5': digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, LOW); digitalWrite(5, LOW); Serial.println("STOP"); break; case 'A': digitalWrite(6, LOW); digitalWrite(7, HIGH); Serial.println("JOINT 1 CLOCK"); delay(200); digitalWrite(6, LOW); digitalWrite(7, LOW); break; case 'B': digitalWrite(6, HIGH ); digitalWrite(7, LOW); Serial.println("JOINT 1 ANTICLOCK"); delay(200); digitalWrite(6, LOW); digitalWrite(7, LOW); break; case 'C': digitalWrite(8, LOW); digitalWrite(9, HIGH); Serial.println("JOINT 2 CLOCK"); delay(200); digitalWrite(8, LOW); digitalWrite(9, LOW); break; case 'D': digitalWrite(8, HIGH); digitalWrite(9, LOW); Serial.println("JOINT 2 ANTICLOCK"); delay(200); digitalWrite(8, LOW); digitalWrite(9, LOW); break; case 'E': digitalWrite(10, LOW); digitalWrite(11, HIGH); Serial.println("JOINT 3 CLOCK");

delay(200); digitalWrite(10, LOW); digitalWrite(11, LOW); break; case 'F': digitalWrite(10, HIGH); digitalWrite(11, LOW); Serial.println("JOINT 3 ANTICLOCK"); delay(200); digitalWrite(10, LOW); digitalWrite(11, LOW); break; case 'G': digitalWrite(12, LOW); digitalWrite(13, HIGH); Serial.println("JOINT 4 CLOCK"); delay(200); digitalWrite(12, LOW); digitalWrite(13, LOW); break; case 'H': digitalWrite(12, HIGH); digitalWrite(13, LOW); Serial.println("JOINT 4 ANTICLOCK"); delay(200); digitalWrite(12, LOW); digitalWrite(13, LOW); break; case 'I': digitalWrite(14, LOW); digitalWrite(15, HIGH); Serial.println("JOINT 5 CLOCK"); delay(200); digitalWrite(14, LOW); digitalWrite(15, LOW); break; case 'J': digitalWrite(14, HIGH); digitalWrite(15, LOW); Serial.println("JOINT 5 ANTICLOCK"); delay(200); digitalWrite(14, LOW); digitalWrite(15, LOW); break; } }}

105) Arduino Atari Joystick Linking for Robotics Control

COMPONENTS AND SUPPLIES Arduino Mega 2560 & Genuino Mega 2560 Any Arduino based card will work

×

1

Adafruit RGB Backlight LCD 16x2 Any type of readable display device

×

1

×

1

×

2

×

1

×

2

×

1

×

2

Analog joystick (Generic) The Joystick you select must have Infrared Capabilities, but you may also use almost any Infrared remote device. Solderless Breadboard Full Size

Jumper wires (generic)

Resistor 10k ohm

IR receiver (generic) Be sure to check if you need to install an inline resistor. Some have them built in. Single Turn Potentiometer- 10k ohms For LCD brightness and contrast control

9V battery (generic) ×

1

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT For use with robotics control when completed as a whole project. The joysticks are recovered from a bygone era of my time, '80s when computers were just taking off. Anyway, these joysticks are infrared, they work, and both have different signals, but on the same timings frequency. One of them is a master having the reset, next, and select menu buttons on it. The other does not.

The oldie but goodie joysticks

Now to the usage video. These joysticks send out some funky monkey types of signals as you will see, I traced it down to three variables that needed to be worked out. Receive the IR signal from one of the joysticks. Set a slight delay to allow the IR device to decipher the signal, for these joysticks it was around 15 to 20 milliseconds. Await the joysticks "End of Transmission" code. This set sends out a third IR pulse at the end, and it is always the same. It is an end of activity signal of sorts.

SCHEMATICS

CODE #include #include int RECV_PIN = 2; int CONFIRM_PIN = 3; IRrecv irrecv(RECV_PIN); decode_results results; LiquidCrystal lcd(22,23,27,26,25,24); void setup() { pinMode(CONFIRM_PIN, OUTPUT); Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver lcd.begin(16, 2); lcd.clear(); lcd.setCursor(0, 0); lcd.print(" IR Recieve and "); lcd.setCursor(0, 1); lcd.print("then output test"); delay(2000); lcd.clear(); } void loop() { digitalWrite(CONFIRM_PIN, LOW); lcd.setCursor(0, 0); lcd.print("Ready to Recieve"); lcd.setCursor(0, 1); lcd.print("Press any button"); if (irrecv.decode(&results)) { Serial.println(results.value, HEX); Serial.println(results.value, DEC); digitalWrite(CONFIRM_PIN, HIGH);

lcd.clear(); lcd.setCursor(0, 0); lcd.print(" HEX = "); lcd.print(results.value, HEX); lcd.setCursor(0, 1); lcd.print(" DEC = "); lcd.print(results.value, DEC); delay(3000); irrecv.resume(); // Receive the next value } }

106) Arduino LED Temperature Indicator

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO ×

1

×

3

×

1

×

16

LED (generic) Any color

Temperature Sensor

Jumper wires (generic)

ABOUT THIS PROJECT tep 1: Get Parts

Arduino Uno/Genuino Breadboard Jumper wires (generic) 3 220Ω resistors 3 LEDs (any color) A temperature sensor (mine is an LM35, but most should work) Step 2: Put Parts in Place

Follow Picture

Step 3: Wire It Up

Wire Set-up Wire it up: >Red LED goes to digital pin 4 through one of the resistors, and ground >Green LED goes to digital pin 3 though a resistor, and ground >Blue LED goes to digital pin 2 through a resistor, and ground >Pin one (the pin on the left) of the temperature sensor goes to 5v >Pin two (the pin in the middle) of the temperature sensor goes to analog pin A2 >pin three (the pin on the right) of the temperature sensor goes to ground Step 4 : Put Code SCHEMATICS

CODE const int hot = 87; //set hot parameter const int cold = 75; //set cold parameter void setup() { pinMode(A2, INPUT); //sensor pinMode(2, OUTPUT); //blue pinMode(3, OUTPUT); //green pinMode(4, OUTPUT); //red Serial.begin(9600); } void loop() { int sensor = analogRead(A2); float voltage = (sensor / 1024.0) * 5.0; float tempC = (voltage - .5) * 100; float tempF = (tempC * 1.8) + 32; Serial.print("temp: "); Serial.print(tempF); if (tempF < cold) { //cold digitalWrite(2, HIGH); digitalWrite(3, LOW); digitalWrite(4, LOW); Serial.println(" It's Cold."); } else if (tempF >= hot) { //hot digitalWrite(2, LOW); digitalWrite(3, LOW);

digitalWrite(4, HIGH); Serial.println(" It's Hot."); } else { //fine digitalWrite(2, LOW); digitalWrite(3, HIGH); digitalWrite(4, LOW); Serial.println(" It's Fine."); } delay(10); }

107) Arduino Portable Electronic Sudoku Game

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

2.8 inch TFT Touch LCD screen Li-Po Rechargeable Battery 600mAh 3.7v (30mm x 50mm x 6mm maximum physical

×

1

×

1

×

1

dimensions) TP4056 Lithium Battery Charger Board Micro USB

×

1

NECESSARY TOOLS AND MACHINES 3D printer with a minimum 160mm x 70mm x 30mm build capacity ABOUT THIS PROJECT Years ago, just for fun, I wrote an excel macro to solve Sudoku puzzles on a desktop computer. It occurred to me that this could be incorporated into an Arduino touchscreen device. The perfect fit for this was an Arduino Uno and a compatible 2.8-inch TFT touchscreen shield.

SCHEMATICS

CODE // Array with following locations: {0 , 1 , 2 3 4, 5, 6, 7, 8, 9,10,11,12, 13 } // Array with following Structure: {Solved, value , X , Y , V1,V2,V3,V4,V5,V6,V7,V8,V9 panel# } colcoord[9] = { 10, 34, 58, 90, 114, 138, 170, 194, 218 }; rowcoord[9] = { 8, 33, 58, 88, 113, 138, 170, 194, 218 }; int location = 1; const int sudoku[81][12]; */ #include // Core graphics library #include // Hardware-specific library #include

#define YP A3 // must be an analog pin, use "An" notation! #define XM A2 // must be an analog pin, use "An" notation! #define YM 9 // can be a digital pin #define XP 8 // can be a digital pin // Revised Touch Callibration numbers #define TS_MINX 130 #define TS_MINY 88 #define TS_MAXX 915 //#define TS_MAXY 927 #define TS_MAXY 880 // For better pressure precision, we need to know the resistance // between X+ and X- Use any multimeter to read it // For the one we're using, its 300 ohms across the X plate TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); #define LCD_CS A3 #define LCD_CD A2 #define LCD_WR A1 #define LCD_RD A0 // optional #define LCD_RESET A4 // Assign human-readable names to some common 16-bit color values: // I had to reverse these colors for my screen int BLACK = 0x0000; int RED = 0x001F; int BLUE = 0xF800; int GREEN = 0x07E0; int YELLOW = 0x07FF; int MAGENTA = 0xF81F; int CYAN = 0xFFE0; int WHITE = 0xFFFF;

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); #define BOX 78 // Block to clear screen #define BOXSIZE 80 #define BUTTON 20 boolean debounce = false; // Used to debounce touch screen input

// Array with following Structure: {value , X , Y , Solved } const byte colcoord[9] = { 10, 34, 58, 90, 114, 138, 170, 194, 218 }; const byte rowcoord[9] = { 8, 33, 58, 88, 113, 138, 170, 194, 218 }; byte location = 1; byte puzzlenum = 1; // These identifier for 5 puzzles stored in memory byte sudoku[82][14]; byte touchlocation = 0; // Used to track the array value that the stylis is closest to in the Sudoku 9x9 framework int delay1 = 400; // Pause input into screen byte tempreading = 0; void setup(void) { // Serial.begin(9600); // Serial.println(F("Paint!")); tft.reset(); uint16_t identifier = tft.readID(); identifier=0x9325; tft.begin(identifier); tft.setRotation(1); tft.fillScreen(BLACK); // **** Splash Screen

tft.drawRoundRect(0, 0, 320, 240, 20, BLUE); tft.drawRoundRect(1, 1, 318, 238, 20, BLUE); byte g = 70; tft.drawCircle(46, g, 25, GREEN); tft.fillCircle(46, g, 20, GREEN); tft.setTextColor(BLACK); tft.setTextSize(3); tft.setCursor(39, g-10); tft.println("S"); tft.drawCircle(91, g+30, 25, BLUE); tft.fillCircle(91, g+30, 20, BLUE);

tft.setTextColor(BLACK); tft.setTextSize(3); tft.setCursor(84, g+20); tft.println("U"); tft.drawCircle(137, g, 25, YELLOW); tft.fillCircle(137, g, 20, YELLOW); tft.setTextColor(BLACK); tft.setTextSize(3); tft.setCursor(130, g-10); tft.println("D"); tft.drawCircle(183, g+30, 25, RED); tft.fillCircle(183, g+30, 20, RED); tft.setTextColor(BLACK); tft.setTextSize(3); tft.setCursor(176, g+20); tft.println("O"); tft.drawCircle(229, g, 25, GREEN); tft.fillCircle(229, g, 20, GREEN); tft.setTextColor(BLACK); tft.setTextSize(3); tft.setCursor(222, g-10); tft.println("K"); tft.drawCircle(274, g+30, 25, YELLOW); tft.fillCircle(274, g+30, 20, YELLOW); tft.setTextColor(BLACK); tft.setTextSize(3); tft.setCursor(267, g+20); tft.println("U"); tft.setTextColor(WHITE); tft.setTextSize(2); tft.setCursor(25, 170); tft.println("Play, Create, Solve"); tft.setTextColor(GREEN); tft.setTextSize(1); tft.setCursor(25, 200); tft.println("By TechKiwiGadgets 2019");

delay(4000); tft.fillScreen(BLACK); drawscreen(); // Clearscreen and setup Sudoku matrix resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero and loading in the coordinates for each touch location loadpaneldata(); // Load specifc Panel identification Data into the Array for each of the 81 locations solvealigndata(); // Sanitize test puzzle data with correct data format // Test Display by showing all values in the puzzle - White are Solved , Blue are others tft.setTextSize(2);

for (byte a = 1; a < 82; a++) { //Test solve or set condition if (sudoku[a][1] != 0) { if (sudoku[a][0] != 0) { tft.setTextColor(WHITE); } else { tft.setTextColor(GREEN); // Set this colour if not a genuine set clue } tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } }

drawbuttons(); pinMode(13, OUTPUT); // testText();

} #define MINPRESSURE 5 #define MAXPRESSURE 1000

// tft.begin(identifier); void loop() { // Read the Touch Screen Locations digitalWrite(13, HIGH); TSPoint p = ts.getPoint(); digitalWrite(13, LOW); // if sharing pins, you'll need to fix the directions of the touchscreen pins pinMode(XM, OUTPUT); pinMode(YP, OUTPUT);

// we have some minimum pressure we consider 'valid' // pressure of 0 means no pressing! if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { /* Serial.print("X = "); Serial.print(p.x); Serial.print("\tY = "); Serial.print(p.y); Serial.print("\tPressure = "); Serial.println(p.z); */ // scale from 0->1023 to tft.width p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240); p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320); // Original Code /* Serial.print("X = "); Serial.print(p.x); Serial.print("\tY = "); Serial.print(p.y); Serial.print("\tPressure = "); Serial.println(p.z); */ // Calculate the position of the screen touch based on the input values of p.x and p.y if ((p.x > 0) && (p.x < 27)) {

// Coloumn 1

if ((p.y > 0) && (p.y < 27)) { touchlocation = 1; } if ((p.y > 28) && (p.y < 53)) { touchlocation = 2; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 3; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 4; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 5; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 6; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 7; }

// Row 1

// Row 2

// Row 3

// Row 4

// Row 5

// Row 6

// Row 7

if ((p.y > 188) && (p.y < 213)) { touchlocation = 8; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 9; } } else if ((p.x > 28) && (p.x < 53)) { if ((p.y > 0) && (p.y < 27)) { touchlocation = 10; } if ((p.y > 28) && (p.y < 53)) { touchlocation = 11; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 12; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 13; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 14; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 15; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 16; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 17; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 18; }

} else if ((p.x > 54) && (p.x < 80)) { if ((p.y > 0) && (p.y < 27)) { touchlocation = 19; } if ((p.y > 28) && (p.y < 53)) {

// Row 8

// Row 9

// Coloumn 2 // Row 1

// Row 2

// Row 3

// Row 4

// Row 5

// Row 6

// Row 7

// Row 8

// Row 9

// Coloumn 3 // Row 1

// Row 2

touchlocation = 20; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 21; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 22; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 23; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 24; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 25; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 26; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 27; }

} else if ((p.x > 81) && (p.x < 107)) { if ((p.y > 0) && (p.y < 27)) { touchlocation = 28; } if ((p.y > 28) && (p.y < 53)) { touchlocation = 29; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 30; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 31; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 32; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 33; }

// Row 3

// Row 4

// Row 5

// Row 6

// Row 7

// Row 8

// Row 9

// Coloumn 4 // Row 1

// Row 2

// Row 3

// Row 4

// Row 5

// Row 6

if ((p.y > 161) && (p.y < 187)) { touchlocation = 34; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 35; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 36; } } else if ((p.x > 108) && (p.x < 133)) { if ((p.y > 0) && (p.y < 27)) { touchlocation = 37; } if ((p.y > 28) && (p.y < 53)) { touchlocation = 38; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 39; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 40; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 41; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 42; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 43; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 44; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 45; } } else if ((p.x > 134) && (p.x < 160)) { if ((p.y > 0) && (p.y < 27)) { touchlocation = 46;

// Row 7

// Row 8

// Row 9

// Coloumn 5 // Row 1

// Row 2

// Row 3

// Row 4

// Row 5

// Row 6

// Row 7

// Row 8

// Row 9

// Coloumn 6 // Row 1

} if ((p.y > 28) && (p.y < 53)) { touchlocation = 47; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 48; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 49; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 50; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 51; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 52; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 53; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 54; }

} else if ((p.x > 161) && (p.x < 187)) { if ((p.y > 0) && (p.y < 27)) { touchlocation = 55; } if ((p.y > 28) && (p.y < 53)) { touchlocation = 56; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 57; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 58; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 59; }

// Row 2

// Row 3

// Row 4

// Row 5

// Row 6

// Row 7

// Row 8

// Row 9

// Coloumn 7 // Row 1

// Row 2

// Row 3

// Row 4

// Row 5

if ((p.y > 134) && (p.y < 160)) { touchlocation = 60; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 61; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 62; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 63; }

} else if ((p.x > 188) && (p.x < 213)) { if ((p.y > 0) && (p.y < 27)) { touchlocation = 64; } if ((p.y > 28) && (p.y < 53)) { touchlocation = 65; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 66; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 67; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 68; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 69; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 70; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 71; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 72; } } else if ((p.x > 214) && (p.x < 240)) {

// Row 6

// Row 7

// Row 8

// Row 9

// Coloumn 8 // Row 1

// Row 2

// Row 3

// Row 4

// Row 5

// Row 6

// Row 7

// Row 8

// Row 9

// Coloumn 9

if ((p.y > 0) && (p.y < 27)) { touchlocation = 73; } if ((p.y > 28) && (p.y < 53)) { touchlocation = 74; } if ((p.y > 54) && (p.y < 80)) { touchlocation = 75; } if ((p.y > 81) && (p.y < 107)) { touchlocation = 76; } if ((p.y > 108) && (p.y < 133)) { touchlocation = 77; } if ((p.y > 134) && (p.y < 160)) { touchlocation = 78; } if ((p.y > 161) && (p.y < 187)) { touchlocation = 79; } if ((p.y > 188) && (p.y < 213)) { touchlocation = 80; } if ((p.y > 214) && (p.y < 240)) { touchlocation = 81; }

// Row 1

// Row 2

// Row 3

// Row 4

// Row 5

// Row 6

// Row 7

// Row 8

// Row 9

} // debounce function to remove issue with first touch screen reading being spurious if (debounce == false) { touchlocation = 0; debounce = true; } // This code only applies to stylis activity within the Sudokumatrix if ( ((p.x < 235)&&(p.y < 230))&& (touchlocation != 0)) {

// tft.fillRect(250, 80, 15, 10, BLACK); /* Serial.print("Y = "); Serial.print(p.x);

Serial.print("\tX = "); Serial.print(p.y); Serial.print("\tLocation = "); Serial.println(touchlocation); */ // Calculate the incremental changes to the data array // Array Structure: {value , X , Y , Solved } // Only increment if has not been solved, Debounce by checking if this is the second time the same range is selected if ((tempreading == touchlocation)&&(sudoku[touchlocation][0]==0)||(tempreading == touchlocation)&&(sudoku[touchlocation][0]==2)) { sudoku[touchlocation][1]++; if (sudoku[touchlocation][1] > 9) { sudoku[touchlocation][1] = 0; } // Test to see if changing an item can be classified as solved if (sudoku[touchlocation][1]!=0) { sudoku[touchlocation][0]=2; // Set to Solved if a manually changed number however flag as manual change with va,ue of 2 } else { sudoku[touchlocation][0]=0; // Set to Not Solved if 0 } // Finally reset all of the data values in this location that have been manually changed to unsolved for (byte u = 1; u < 82; u++) { // If preprogrammed from a game then leave values otherwise reset data to baseline if (sudoku[u][0]!=1){ for (byte q = 4; q < 13; q++) { sudoku[u][q]=q-3; } } } } // //

tft.setTextColor(WHITE); tft.setTextSize(1); tft.setCursor(250, 80); tft.println(touchlocation);

// Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[touchlocation][3], sudoku[touchlocation][2], 15, 15, BLACK); tft.setTextSize(2); if (sudoku[touchlocation][0] != 0) { // Do not draw 0 just leave blank square if (sudoku[touchlocation][0] == 1) {

tft.setTextColor(WHITE); } else if (sudoku[touchlocation][0] == 2) { tft.setTextColor(GREEN); // Set this colour if not a genuine set clue } tft.setCursor( sudoku[touchlocation][3], sudoku[touchlocation][2]); tft.println(sudoku[touchlocation][1]); } if (tempreading == touchlocation) { delay(delay1); }

tempreading = touchlocation; // take a first sample then repeat and compare to debounce

} // Inside touch sensor reading if statement // HOME Button Pressed ************************************************ if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 10)&&(p.x < 40))) {

tft.fillCircle(280, 30, 20, WHITE); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(268, 27); tft.println("HOME"); delay(delay1/2); drawscreen(); // Clearscreen and setup Sudoku matrix resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero: refreshdisplay(); drawbuttons(); } // PLAY Button Pressed ************************************************ if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 80)&&(p.x < 110))) {

//PLAY Button pressed //Button 2 tft.fillCircle(280, 90, 20, WHITE); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(268, 87); tft.println("PLAY");

delay(delay1/2); drawscreen(); // Clearscreen and setup Sudoku matrix resetmatrix(); // Initialize the sudoku matrix by setting all locations to zero: loadtestpuzzle1(); // Loads test puzzle into the location array

solvealigndata(); // Sanitize test puzzle data with correct data format

refreshdisplay(); // Only display testpuzzle data locations that are drawbuttons(); // Redraw buttons togive push button effect tft.setCursor(277, 97); tft.println(puzzlenum); // Manage Puzzle Number puzzlenum++; // increment puzzle number if (puzzlenum > 5) { puzzlenum = 1; } } // HELP Button Pressed ************************************************ if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 140)&&(p.x < 160))) { //Button 3 tft.fillCircle(280, 150, 20, WHITE); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(268, 147); tft.println("HELP");

delay(delay1/2); // // // //

drawscreen(); // Clearscreen and setup Sudoku matrix solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule

helpbutton(); // Run algorythm and test for incorrect locations then highlight in red //

reversesolve();

delay(800);// Display the changes before reverting to original colors

refreshdisplay(); // Only display testpuzzle data locations that are drawbuttons(); // Redraw buttons togive push button effect } // SOLVE Button Pressed ************************************************ if ( ((p.y > 255)&&(p.y < 300))&& ((p.x > 200)&&(p.x < 220))) {

//SOLVE Button Pressed //Button 4 tft.fillCircle(280, 210, 20, WHITE); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(266, 207); tft.println("SOLVE");

delay(delay1/2);

solvepanel(); // Solve Panel rule solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule reversesolvecolor();

uniquecandidate(); // Test solvealigndata(); reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor(); solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule solvepanel(); // Solve Panel rule reversesolvecolor();

solvepanel(); // Solve Panel rule solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule reversesolvecolor(); uniquecandidate(); // Test solvealigndata(); reversesolvecolor(); solvepanel(); // Solve Panel rule solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule reversesolvecolor(); uniquecandidate(); // Test solvealigndata(); reversesolvecolor(); solvepanel(); // Solve Panel rule solvehorizontal(); // Solve horiontal rule solvevertical(); // Solve vertical rule reversesolvecolor(); uniquecandidate(); // Test solvealigndata(); reversesolvecolor();

drawscreen(); // Clearscreen and setup Sudoku matrix refreshdisplay(); // Only display testpuzzle data locations that are helpbutton(); // Run algorythm and test for incorrect locations then highlight in red drawbuttons(); // Redraw buttons togive push button effect }

/* Serial.print("Y = "); Serial.print(p.x); Serial.print("\tX = "); Serial.println(p.y); */

p.z = 0;// Force the sensor value below threshold to avoid ghost values } }

void loadtestpuzzle1(){ // Test Puzzle example 1 loaded into array if (puzzlenum == 1 ){ // Load Numbers sudoku[1][1] = 2; sudoku[3][1] = 9; sudoku[19][1] = 3; sudoku[21][1] = 5; sudoku[5][1] = 6; sudoku[6][1] = 3; sudoku[14][1] = 2; sudoku[23][1] = 9; sudoku[7][1] = 4; sudoku[9][1] = 8; sudoku[26][1] = 7; sudoku[39][1] = 1; sudoku[46][1] = 9; sudoku[47][1] = 7; sudoku[48][1] = 2; sudoku[31][1] = 9; sudoku[32][1] = 8; sudoku[50][1] = 1; sudoku[51][1] = 6; sudoku[34][1] = 7; sudoku[35][1] = 1; sudoku[36][1] = 6; sudoku[43][1] = 2; sudoku[56][1] = 3; sudoku[73][1] = 5; sudoku[75][1] = 6; sudoku[59][1] = 7; sudoku[68][1] = 3; sudoku[76][1] = 1; sudoku[77][1] = 4; sudoku[61][1] = 6; sudoku[63][1] = 1; sudoku[79][1] = 8; sudoku[81][1] = 7; // Set the Solved Flag for each sudoku[1][0] = 1; sudoku[3][0] = 1; sudoku[19][0] = 1; sudoku[21][0] = 1; sudoku[5][0] = 1; sudoku[6][0] = 1; sudoku[14][0] = 1; sudoku[23][0] = 1; sudoku[7][0] = 1; sudoku[9][0] = 1; sudoku[26][0] = 1;

sudoku[39][0] = 1; sudoku[46][0] = 1; sudoku[47][0] = 1; sudoku[48][0] = 1; sudoku[31][0] = 1; sudoku[32][0] = 1; sudoku[50][0] = 1; sudoku[51][0] = 1; sudoku[34][0] = 1; sudoku[35][0] = 1; sudoku[36][0] = 1; sudoku[43][0] = 1; sudoku[56][0] = 1; sudoku[73][0] = 1; sudoku[75][0] = 1; sudoku[59][0] = 1; sudoku[68][0] = 1; sudoku[76][0] = 1; sudoku[77][0] = 1; sudoku[61][0] = 1; sudoku[63][0] = 1; sudoku[79][0] = 1; sudoku[81][0] = 1; } else if (puzzlenum == 2 ){ // Load Numbers sudoku[1][1] = 4; sudoku[10][1] = 2; sudoku[19][1] = 1; sudoku[5][1] = 2; sudoku[15][1] = 4; sudoku[24][1] = 5; sudoku[25][1] = 2; sudoku[17][1] = 8; sudoku[18][1] = 6;

sudoku[29][1] = 3; sudoku[30][1] = 2; sudoku[37][1] = 9; sudoku[39][1] = 5; sudoku[46] [1] = 7; sudoku[47][1] = 6; sudoku[31][1] = 6; sudoku[40][1] = 4; sudoku[41][1] = 8; sudoku[42][1] = 3; sudoku[51] [1] = 2; sudoku[35][1] = 4; sudoku[36][1] = 1; sudoku[43][1] = 6; sudoku[45][1] = 2; sudoku[52] [1] = 3; sudoku[53][1] = 5;

sudoku[57][1] = 1; sudoku[64][1] = 3; sudoku[65][1] = 8; sudoku[58][1] = 7; sudoku[67][1] = 5; sudoku[77][1] = 9; sudoku[63][1] = 9; sudoku[72][1] = 7; sudoku[81][1] = 5;

// Set the Solved Flag for each sudoku[1][0] = 1; sudoku[10][0] = 1; sudoku[19][0] = 1; sudoku[5][0] = 1; sudoku[15][0] = 1; sudoku[24][0] = 1;

sudoku[25][0] = 1; sudoku[17][0] = 1; sudoku[18][0] = 1;

sudoku[29][0] = 1; sudoku[30][0] = 1; sudoku[37][0] = 1; sudoku[39][0] = 1; sudoku[46] [0] = 1; sudoku[47][0] = 1; sudoku[31][0] = 1; sudoku[40][0] = 1; sudoku[41][0] = 1; sudoku[42][0] = 1; sudoku[51] [0] = 1; sudoku[35][0] = 1; sudoku[36][0] = 1; sudoku[43][0] = 1; sudoku[45][0] = 1; sudoku[52] [0] = 1; sudoku[53][0] = 1;

sudoku[57][0] = 1; sudoku[64][0] = 1; sudoku[65][0] = 1; sudoku[58][0] = 1; sudoku[67][0] = 1; sudoku[77][0] = 1; sudoku[63][0] = 1; sudoku[72][0] = 1; sudoku[81][0] = 1; } else if (puzzlenum == 3 ){ // Load Numbers sudoku[12][1] = 8; sudoku[19][1] = 4; sudoku[5][1] = 2; sudoku[13][1] = 9; sudoku[14][1] = 4; sudoku[22][1] = 7; sudoku[24][1] = 8; sudoku[7][1] = 8; sudoku[9][1] = 7; sudoku[25][1] = 2; sudoku[27][1] = 9;

sudoku[28][1] = 1; sudoku[29][1] = 2; sudoku[38][1] = 4; sudoku[39][1] = 3; sudoku[30] [1] = 7; sudoku[31][1] = 5; sudoku[41][1] = 8; sudoku[51][1] = 7; sudoku[43][1] = 5; sudoku[44][1] = 7; sudoku[52][1] = 9; sudoku[53][1] = 2; sudoku[54] [1] = 4;

sudoku[55][1] = 8; sudoku[57][1] = 9; sudoku[73][1] = 6; sudoku[75][1] = 4; sudoku[58][1] = 1; sudoku[60][1] = 2; sudoku[68][1] = 6; sudoku[69][1] = 9; sudoku[77] [1] = 3;

sudoku[70][1] = 1; sudoku[63][1] = 3;

// Set the Solved Flag for each sudoku[12][0] = 1; sudoku[19][0] = 1; sudoku[5][0] = 1; sudoku[13][0] = 1; sudoku[14][0] = 1; sudoku[22][0] = 1; sudoku[24][0] = 1; sudoku[7][0] = 1; sudoku[9][0] = 1; sudoku[25][0] = 1; sudoku[27][0] = 1;

sudoku[28][0] = 1; sudoku[29][0] = 1; sudoku[38][0] = 1; sudoku[39][0] = 1; sudoku[30] [0] = 1; sudoku[31][0] = 1; sudoku[41][0] = 1; sudoku[51][0] = 1; sudoku[43][0] = 1; sudoku[44][0] = 1; sudoku[52][0] = 1; sudoku[53][0] = 1; sudoku[54] [0] = 1;

sudoku[55][0] = 1; sudoku[57][0] = 1; sudoku[73][0] = 1; sudoku[75][0] = 1; sudoku[58][0] = 1; sudoku[60][0] = 1; sudoku[68][0] = 1; sudoku[69][0] = 1; sudoku[77] [0] = 1; sudoku[70][0] = 1; sudoku[63][0] = 1; } else if (puzzlenum == 4 ){ // Load Numbers sudoku[3][1] = 6; sudoku[12][1] = 2; sudoku[5][1] = 7; sudoku[6][1] = 9; sudoku[13][1] = 1; sudoku[16][1] = 6; sudoku[17][1] = 5; sudoku[18][1] = 4; sudoku[25][1] = 7; sudoku[26] [1] = 1;

sudoku[29][1] = 6; sudoku[30][1] = 5; sudoku[37][1] = 8; sudoku[46][1] = 1; sudoku[48] [1] = 3; sudoku[33][1] = 4; sudoku[40][1] = 7; sudoku[41][1] = 2; sudoku[42][1] = 5; sudoku[49]

[1] = 8; sudoku[34][1] = 9; sudoku[36][1] = 8; sudoku[45][1] = 3; sudoku[52][1] = 4; sudoku[53] [1] = 7;

sudoku[56][1] = 3; sudoku[57][1] = 7; sudoku[64][1] = 6; sudoku[65][1] = 4;sudoku[66][1] = 1; sudoku[76][1] = 6; sudoku[77][1] = 4; sudoku[69][1] = 3; sudoku[70][1] = 8; sudoku[79][1] = 5;

// Set the Solved Flag for each sudoku[3][0] = 1; sudoku[12][0] = 1; sudoku[5][0] = 1; sudoku[6][0] = 1; sudoku[13][0] = 1; sudoku[16][0] = 1; sudoku[17][0] = 1; sudoku[18][0] = 1; sudoku[25][0] = 1; sudoku[26] [0] = 1;

sudoku[29][0] = 1; sudoku[30][0] = 1; sudoku[37][0] = 1; sudoku[46][0] = 1; sudoku[48] [0] = 1; sudoku[33][0] = 1; sudoku[40][0] = 1; sudoku[41][0] = 1; sudoku[42][0] = 1; sudoku[49] [0] = 1; sudoku[34][0] = 1; sudoku[36][0] = 1; sudoku[45][0] = 1; sudoku[52][0] = 1; sudoku[53] [0] = 1;

sudoku[56][0] = 1; sudoku[57][0] = 1; sudoku[64][0] = 1; sudoku[65][0] = 1;sudoku[66][0] = 1; sudoku[76][0] = 1; sudoku[77][0] = 1; sudoku[69][0] = 1; sudoku[70][0] = 1; sudoku[79][0] = 1; } else if (puzzlenum == 5 ){ // Load Numbers sudoku[2][1] = 3; sudoku[3][1] = 2; sudoku[12][1] = 6; sudoku[21][1] = 9;

sudoku[4][1] = 9; sudoku[5][1] = 8; sudoku[22][1] = 2; sudoku[17][1] = 3; sudoku[27][1] = 7;

sudoku[30][1] = 7; sudoku[47][1] = 9; sudoku[31][1] = 1; sudoku[40][1] = 3; sudoku[42][1] = 5; sudoku[51][1] = 4; sudoku[35][1] = 5; sudoku[52][1] = 6;

sudoku[55][1] = 2; sudoku[65][1] = 6; sudoku[60][1] = 9; sudoku[77][1] = 5; sudoku[78][1] = 3; sudoku[61][1] = 3; sudoku[70][1] = 7; sudoku[79][1] = 2; sudoku[80][1] = 6;

// Set the Solved Flag for each sudoku[2][0] = 1; sudoku[3][0] = 1; sudoku[12][0] = 1; sudoku[21][0] = 1; sudoku[4][0] = 1; sudoku[5][0] = 1; sudoku[22][0] = 1; sudoku[17][0] = 1; sudoku[27][0] = 1;

sudoku[30][0] = 1; sudoku[47][0] = 1; sudoku[31][0] = 1; sudoku[40][0] = 1; sudoku[42][0] = 1; sudoku[51][0] = 1; sudoku[35][0] = 1; sudoku[52][0] = 1;

sudoku[55][0] = 1; sudoku[65][0] = 1; sudoku[60][0] = 1; sudoku[77][0] = 1; sudoku[78][0] = 1; sudoku[61][0] = 1; sudoku[70][0] = 1; sudoku[79][0] = 1; sudoku[80][0] = 1; } }

void refreshdisplay() { //Refresh the display once a value has changed tft.setTextSize(2); for (byte a = 1; a < 82; a++) { //Test solve or set condition if (sudoku[a][1] != 0) { //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); if (sudoku[a][0] != 0) { // Do not draw 0 just leave blank square if (sudoku[a][0] == 1) { tft.setTextColor(WHITE); } else if (sudoku[a][0] == 2) { tft.setTextColor(GREEN); // Set this colour if not a genuine set clue } tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); }

} } }

void drawscreen(){ //

tft.fillScreen(BLACK);

// Setup Screen GREEN = 0x07E0;

tft.fillRect(1, 1, 239, 239, BLACK); tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); tft.drawRect(0+BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE); tft.drawRect(0+BOXSIZE+BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE); tft.drawRect(0, BOXSIZE, BOXSIZE, BOXSIZE, WHITE);

tft.drawRect(0+BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE); tft.drawRect(0+BOXSIZE+BOXSIZE, BOXSIZE, BOXSIZE, BOXSIZE, WHITE); tft.drawRect(0, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE); tft.drawRect(0+BOXSIZE, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE); tft.drawRect(0+BOXSIZE+BOXSIZE, BOXSIZE*2, BOXSIZE, BOXSIZE, WHITE); }

void resetmatrix(){ // Initialize the sudoku matrix by setting all locations to zero and loading in the coordinates for each touch location byte hole = 1; for (byte a = 0; a < 9; a++) { for (byte b = 0; b < 9; b++) { sudoku[hole][0] = 0; // Solve Flag sudoku[hole][1] = 0; // Display Value sudoku[hole][2] = colcoord[a]; // Matrix Column coordinate sudoku[hole][3] = rowcoord[b]; // Matrix Row coordinate sudoku[hole][4] = 1; // V1 sudoku[hole][5] = 2; // V2 sudoku[hole][6] = 3; // V3 sudoku[hole][7] = 4; // V4 sudoku[hole][8] = 5; // V5 sudoku[hole][9] = 6; // V6 sudoku[hole][10] = 7; // V7 sudoku[hole][11] = 8; // V8 sudoku[hole][12] = 9; // V9 hole++; } } }

void drawbuttons() { // Setup Buttons GREEN = 0x07E0; //Button 1 tft.drawCircle(280, 30, 24, GREEN); tft.fillCircle(280, 30, 20, GREEN); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(268, 27); tft.println("HOME"); //Button 2 tft.drawCircle(280, 90, 24, YELLOW);

tft.fillCircle(280, 90, 20, YELLOW); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(268, 87); tft.println("PLAY"); //Button 3 tft.drawCircle(280, 150, 24, MAGENTA); tft.fillCircle(280, 150, 20, MAGENTA); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(268, 147); tft.println("HELP");

//Button 4 tft.drawCircle(280, 210, 24, BLUE); tft.fillCircle(280, 210, 20, BLUE); tft.setTextColor(BLACK); tft.setTextSize(1); tft.setCursor(266, 207); tft.println("SOLVE");

} void solvealigndata(){ // Once a location is marked as solved then all data in that location nees to be set to Zero for (byte a = 1; a < 82; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // If location solved then zero out all data in array except correct value /* Serial.print(a);

Serial.print(" ");

Serial.print(sudoku[a][1]); Serial.print(3+sudoku[a][1]); Serial.print(sudoku[a][4]); Serial.print(sudoku[a][5]); Serial.print(sudoku[a][6]); Serial.print(sudoku[a][7]); Serial.print(sudoku[a][8]);

Serial.print(" "); Serial.print(" ");

Serial.print(sudoku[a][9]); Serial.print(sudoku[a][10]); Serial.print(sudoku[a][11]); Serial.println(sudoku[a][12]); */ sudoku[a][4] = 0; // V1 sudoku[a][5] = 0; // V2 sudoku[a][6] = 0; // V3 sudoku[a][7] = 0; // V4 sudoku[a][8] = 0; // V5 sudoku[a][9] = 0; // V6 sudoku[a][10] = 0; // V7 sudoku[a][11] = 0; // V8 sudoku[a][12] = 0; // V9 // Now poke the answer into the correct location sudoku[a][(sudoku[a][1]+3)] = sudoku[a][1]; // Load the solved value into the array /* Serial.print(a);

Serial.print(" ");

Serial.print(sudoku[a][1]); Serial.print(3+sudoku[a][1]); Serial.print(sudoku[a][4]); Serial.print(sudoku[a][5]); Serial.print(sudoku[a][6]); Serial.print(sudoku[a][7]); Serial.print(sudoku[a][8]); Serial.print(sudoku[a][9]); Serial.print(sudoku[a][10]); Serial.print(sudoku[a][11]);

Serial.print(" "); Serial.print(" ");

Serial.println(sudoku[a][12]); */

} }

} void reversesolve(){ // subroutine to reverse engineer solved locations in the matrix and label themas solved byte tempcount = 0; for (byte a = 1; a < 82; a++) { // Cycle through all locations /* Serial.print(a);

Serial.print(" ");

Serial.print(sudoku[a][0]); //

Serial.print(" ");

Serial.print(3+sudoku[a][1]);

Serial.print(" ");

Serial.print(sudoku[a][4]); Serial.print(sudoku[a][5]); Serial.print(sudoku[a][6]); Serial.print(sudoku[a][7]); Serial.print(sudoku[a][8]); Serial.print(sudoku[a][9]); Serial.print(sudoku[a][10]); Serial.print(sudoku[a][11]); Serial.println(sudoku[a][12]); */ if (sudoku[a][0] == 0) { // Ignore location if already solved

// Read each and count the number that have been elimated tempcount = 0; for (byte b = 4; b < 13; b++) { if (sudoku[a][b] == 0) {// If equal to 0 then count tempcount++; } } if (tempcount == 8){ // If only one valid result then find again then mark location as solved for (byte c = 4; c < 13; c++) { // Read each and identify the only solution if (sudoku[a][c] > 0) { sudoku[a][0] = 1; // Set Solved Location Flag sudoku[a][1] = sudoku[a][c]; // Set value } } } } /* Serial.print(a);

Serial.print(" ");

Serial.print(sudoku[a][0]); Serial.print(tempcount);

Serial.print(" "); Serial.print(" ");

Serial.print(sudoku[a][4]); Serial.print(sudoku[a][5]); Serial.print(sudoku[a][6]); Serial.print(sudoku[a][7]); Serial.print(sudoku[a][8]); Serial.print(sudoku[a][9]); Serial.print(sudoku[a][10]); Serial.print(sudoku[a][11]); Serial.println(sudoku[a][12]); */ } }

void reversesolvecolor(){ // subroutine to reverse engineer solved locations in the matrix and label themas solved byte tempcount = 0; for (byte a = 1; a < 82; a++) { // Cycle through all locations /* Serial.print(a);

Serial.print(" ");

Serial.print(sudoku[a][0]); //

Serial.print(" ");

Serial.print(3+sudoku[a][1]);

Serial.print(" ");

Serial.print(sudoku[a][4]); Serial.print(sudoku[a][5]); Serial.print(sudoku[a][6]); Serial.print(sudoku[a][7]); Serial.print(sudoku[a][8]); Serial.print(sudoku[a][9]); Serial.print(sudoku[a][10]); Serial.print(sudoku[a][11]); Serial.println(sudoku[a][12]); */ if (sudoku[a][0] == 0) { // Ignore location if already solved // Read each and count the number that have been elimated tempcount = 0; for (byte b = 4; b < 13; b++) { if (sudoku[a][b] == 0) {// If equal to 0 then count tempcount++; } } if (tempcount == 8){ // If only one valid result then find again then mark location as solved for (byte c = 4; c < 13; c++) { // Read each and identify the only solution if (sudoku[a][c] > 0) {

sudoku[a][0] = 2; // Set Solved Location Flag sudoku[a][1] = sudoku[a][c]; // Set value } } } } /* Serial.print(a);

Serial.print(" ");

Serial.print(sudoku[a][0]); Serial.print(tempcount);

Serial.print(" "); Serial.print(" ");

Serial.print(sudoku[a][4]); Serial.print(sudoku[a][5]); Serial.print(sudoku[a][6]); Serial.print(sudoku[a][7]); Serial.print(sudoku[a][8]); Serial.print(sudoku[a][9]); Serial.print(sudoku[a][10]); Serial.print(sudoku[a][11]); Serial.println(sudoku[a][12]); */ } }

void solvehorizontal(){ // Take Solved locations and apply horizontal rule // Cycle through all locations and using solved flag remove all associate horizontal possibilities

/* for (byte d = 1; d < 82; d++) { // Cycle through all locations

Serial.print(d);

Serial.print(" ");

Serial.print(sudoku[d][0]);

Serial.print(" ");

Serial.print(sudoku[d][4]); Serial.print(sudoku[d][5]); Serial.print(sudoku[d][6]); Serial.print(sudoku[d][7]); Serial.print(sudoku[d][8]); Serial.print(sudoku[d][9]); Serial.print(sudoku[d][10]); Serial.print(sudoku[d][11]); Serial.println(sudoku[d][12]); } */ // ROW 1 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 1; a < 10; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 1; r < 10; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } }

// ROW 2 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 10; a < 19; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 10; r < 19; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) {

sudoku[r][sudoku[a][1]+3] = 0; } } } } // ROW 3 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 19; a < 28; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 19; r < 28; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } }

// ROW 4 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 28; a < 37; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 28; r < 37; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } // ROW 5 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 37; a < 46; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 37; r < 46; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } }

}

// ROW 6 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 46; a < 55; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 46; r < 55; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } // ROW 7 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 55; a < 64; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 55; r < 64; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } }

// ROW 8 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 64; a < 73; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 64; r < 73; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } // ROW 9 ************************

// Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 73; a < 82; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 73; r < 82; r++) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } /* for (byte e = 1; e < 82; e++) { // Cycle through all locations Serial.print(e); Serial.print(" "); Serial.print(sudoku[e][0]);

Serial.print(" ");

Serial.print(sudoku[e][4]); Serial.print(sudoku[e][5]); Serial.print(sudoku[e][6]); Serial.print(sudoku[e][7]); Serial.print(sudoku[e][8]); Serial.print(sudoku[e][9]); Serial.print(sudoku[e][10]); Serial.print(sudoku[e][11]); Serial.println(sudoku[e][12]); } */ }

void solvevertical(){ // Take Solved locations and apply horizontal rule // Cycle through all locations and using solved flag remove all associate vertical possibilities

/* for (byte d = 1; d < 82; d++) { // Cycle through all locations Serial.print(d); Serial.print(" "); Serial.print(sudoku[d][0]);

Serial.print(" ");

Serial.print(sudoku[d][4]); Serial.print(sudoku[d][5]); Serial.print(sudoku[d][6]); Serial.print(sudoku[d][7]); Serial.print(sudoku[d][8]); Serial.print(sudoku[d][9]); Serial.print(sudoku[d][10]); Serial.print(sudoku[d][11]); Serial.println(sudoku[d][12]); } */ // COL 1 ************************ // Step through each of Col locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 1; a < 74; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 1; r < 74; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } }

// COL 2 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 2; a < 75; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry

for (byte r = 2; r < 75; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } // COL 3 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 3; a < 76; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 3; r < 76; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } }

// COL 4 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 4; a < 77; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 4; r < 77; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } // COL 5 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 5; a < 78; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 5; r < 78; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; }

} } }

// COL 6 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 6; a < 79; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 6; r < 79; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } // COL 7 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 7; a < 80; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 7; r < 80; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } }

// COL 8 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 8; a < 81; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 8; r < 81; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } }

// COL 9 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 9; a < 82; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 9; r < 83; r=r+9) { if ((sudoku[r][sudoku[a][1]+3] == sudoku[a][1] )&& (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } /* for (byte e = 1; e < 82; e++) { // Cycle through all locations Serial.print(e); Serial.print(" "); Serial.print(sudoku[e][0]);

Serial.print(" ");

Serial.print(sudoku[e][4]); Serial.print(sudoku[e][5]); Serial.print(sudoku[e][6]); Serial.print(sudoku[e][7]); Serial.print(sudoku[e][8]); Serial.print(sudoku[e][9]); Serial.print(sudoku[e][10]); Serial.print(sudoku[e][11]); Serial.println(sudoku[e][12]); } */ }

void solvepanel(){ // Take Solved locations and apply horizontal rule // Cycle through all locations and using solved flag remove all associate panel possibilities

/* for (byte d = 1; d < 82; d++) { // Cycle through all locations Serial.print(d); Serial.print(" "); Serial.print(sudoku[d][0]); Serial.print(" "); Serial.print(sudoku[d][4]); Serial.print(sudoku[d][5]); Serial.print(sudoku[d][6]); Serial.print(sudoku[d][7]); Serial.print(sudoku[d][8]); Serial.print(sudoku[d][9]); Serial.print(sudoku[d][10]); Serial.print(sudoku[d][11]); Serial.println(sudoku[d][12]); } */

// PANEL Algorythm ************************ // Step through each of locations and delete duplicates of the Solved location using the panel formulae. Ignore the current location you are solving for for (byte a = 1; a < 82; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 1; r < 82; r++) { // Step through all locations if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { // Identify the locations on the Same Panel if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { sudoku[r][sudoku[a][1]+3] = 0; } } } } } /*

for (byte e = 1; e < 82; e++) { // Cycle through all locations Serial.print(e); Serial.print(" "); Serial.print(sudoku[e][0]); Serial.print(" ");

Serial.print(sudoku[e][4]); Serial.print(sudoku[e][5]); Serial.print(sudoku[e][6]); Serial.print(sudoku[e][7]); Serial.print(sudoku[e][8]); Serial.print(sudoku[e][9]); Serial.print(sudoku[e][10]); Serial.print(sudoku[e][11]); Serial.println(sudoku[e][12]); */ }

void loadpaneldata(){ // Load specifc Panel identification Data into the Array for each of the 81 locations

// Load Numbers // Panel 1 sudoku[1][13] = 1; sudoku[2][13] = 1; sudoku[3][13] = 1; sudoku[10][13] = 1; sudoku[11][13] = 1; sudoku[12][13] = 1; sudoku[19][13] = 1; sudoku[20][13] = 1; sudoku[21][13] = 1; // Panel 2 sudoku[4][13] = 2; sudoku[5][13] = 2; sudoku[6][13] = 2; sudoku[13][13] = 2; sudoku[14][13] = 2; sudoku[15][13] = 2; sudoku[22][13] = 2; sudoku[23][13] = 2; sudoku[24][13] = 2; // Panel 3 sudoku[7][13] = 3; sudoku[8][13] = 3; sudoku[9][13] = 3; sudoku[16][13] = 3; sudoku[17][13] = 3; sudoku[18][13] = 3; sudoku[25][13] = 3; sudoku[26][13] = 3; sudoku[27][13] = 3; // Panel 4 sudoku[28][13] = 4; sudoku[29][13] = 4; sudoku[30][13] = 4; sudoku[37][13] = 4; sudoku[38][13] = 4; sudoku[39][13] = 4; sudoku[46][13] = 4; sudoku[47][13] = 4; sudoku[48][13] = 4; // Panel 5 sudoku[31][13] = 5; sudoku[32][13] = 5; sudoku[33][13] = 5; sudoku[40][13] = 5; sudoku[41][13] = 5; sudoku[42][13] = 5; sudoku[49][13] = 5; sudoku[50][13] = 5; sudoku[51][13] = 5; // Panel 6 sudoku[34][13] = 6; sudoku[35][13] = 6; sudoku[36][13] = 6; sudoku[43][13] = 6; sudoku[44][13] = 6; sudoku[45][13] = 6; sudoku[52][13] = 6; sudoku[53][13] = 6; sudoku[54][13] = 6; // Panel 7

sudoku[55][13] = 7; sudoku[56][13] = 7; sudoku[57][13] = 7; sudoku[64][13] = 7; sudoku[65][13] = 7; sudoku[66][13] = 7; sudoku[73][13] = 7; sudoku[74][13] = 7; sudoku[75][13] = 7; // Panel 8 sudoku[58][13] = 8; sudoku[59][13] = 8; sudoku[60][13] = 8; sudoku[67][13] = 8; sudoku[68][13] = 8; sudoku[69][13] = 8; sudoku[76][13] = 8; sudoku[77][13] = 8; sudoku[78][13] = 8; // Panel 9 sudoku[61][13] = 9; sudoku[62][13] = 9; sudoku[63][13] = 9; sudoku[70][13] = 9; sudoku[71][13] = 9; sudoku[72][13] = 9; sudoku[79][13] = 9; sudoku[80][13] = 9; sudoku[81][13] = 9; } // Used to identify and highlight errors in a current matrix - use solve method however instead of solving outcome just highlight conflicts in red void helpbutton(){

// Horizontal ********************* // ROW 1 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 1; a < 10; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 1; r < 10; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// ROW 2 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 10; a < 19; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any

occurences that are already in scope of enquiry for (byte r = 10; r < 19; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // ROW 3 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 19; a < 28; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 19; r < 28; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// ROW 4 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 28; a < 37; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 28; r < 37; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded

//First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // ROW 5 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 37; a < 46; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 37; r < 46; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// ROW 6 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 46; a < 55; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 46; r < 55; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); }

} } } // ROW 7 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 55; a < 64; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 55; r < 64; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// ROW 8 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 64; a < 73; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 64; r < 73; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // ROW 9 ************************ // Step through each of ROW locations and delete duplicates of the Solved location. Ignore

the current location you are solving for for (byte a = 73; a < 82; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 73; r < 82; r++) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // Vertical **************** // COL 1 ************************ // Step through each of Col locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 1; a < 74; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 1; r < 74; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// COL 2 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 2; a < 75; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry

for (byte r = 2; r < 75; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // COL 3 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 3; a < 76; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 3; r < 76; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// COL 4 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 4; a < 77; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 4; r < 77; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location

tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // COL 5 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 5; a < 78; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 5; r < 78; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// COL 6 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 6; a < 79; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 6; r < 79; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } }

} } // COL 7 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 7; a < 80; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 7; r < 80; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } }

// COL 8 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for for (byte a = 8; a < 81; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 8; r < 81; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // COL 9 ************************ // Step through each of COL locations and delete duplicates of the Solved location. Ignore the current location you are solving for

for (byte a = 9; a < 82; a=a+9) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 9; r < 83; r=r+9) { if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } // Panels ******************* // PANEL Algorythm ************************ // Step through each of locations and delete duplicates of the Solved location using the Oanel formulae. Ignore the current location you are solving for for (byte a = 1; a < 82; a++) { // Cycle through all locations if (sudoku[a][0] > 0) { // Identify the locations that are already solved and delete any occurences that are already in scope of enquiry for (byte r = 1; r < 82; r++) { // Step through all locations if ((sudoku[a][13] == sudoku[r][13]) && (a!=r)) { // Identify the locations on the Same Panel if ((sudoku[a][1] == sudoku[r][1] ) && (a!=r)) { // Current location is not a master value and it is duplicate then color RED // Refresh only the location concerned with new value and show colour coded //First Clear Location tft.fillRect(sudoku[a][3], sudoku[a][2], 15, 15, BLACK); tft.setTextSize(2); tft.setTextColor(RED); tft.setCursor( sudoku[a][3], sudoku[a][2]); tft.println(sudoku[a][1]); } } } } }

// Horizontal conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE

// Vertical conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE // Panel conflict help function - Step through data and identify manually changed locations as conflicts in RED. Leave items set at WHITE as WHITE

}

void uniquecandidate() { // Each panel, row and column on a Sudoku board must contain every number between 1 and 9. // Therefore, if a number, say 4, can only be put in a single cell within a block/column/row, then that number is guaranteed to fit there. /* for (byte d = 1; d < 82; d++) { // Cycle through all locations Serial.print(d); Serial.print(" "); Serial.print(sudoku[d][0]); Serial.print(" "); Serial.print(sudoku[d][1]); Serial.print(" "); Serial.print(sudoku[d][4]); Serial.print(sudoku[d][5]); Serial.print(sudoku[d][6]); Serial.print(sudoku[d][7]); Serial.print(sudoku[d][8]); Serial.print(sudoku[d][9]); Serial.print(sudoku[d][10]); Serial.print(sudoku[d][11]); Serial.println(sudoku[d][12]); } */ byte tempcount = 0; for (byte p = 1; p < 10; p++) { // Cycle through all panels 1 to 9 for (byte v = 1; v < 10; v++) { // Step through all possible unique location values in each panel

for (byte r = 1; r < 82; r++) { // Step through all locations if (sudoku[r][13] == p) { //Only operate on those locations that are in this panel

if (sudoku[r][v+3] == v) {// Count this if value is what we are looking for tempcount++; } } } // Check if unique if ( tempcount == 1) { // This is a unique value so reset the location with this being a solved location // Repeat process to locate unique location for (byte r = 1; r < 82; r++) { // Step through all locations and then mark as solved if (sudoku[r][13] == p) { //Only operate on those locations that are in this panel if (sudoku[r][v+3] == v) {// Count this if value is what we are looking for // Now poke the answer into the correct location if (sudoku[r][0] == 0) { // Change to solved but remain green sudoku[r][0] = 2; } sudoku[r][1] = v; } } } } // Reset temp counter tempcount = 0; } } /* for (byte d = 1; d < 82; d++) { // Cycle through all locations Serial.print(d); Serial.print(" "); Serial.print(sudoku[d][0]); Serial.print(" "); Serial.print(sudoku[d][1]); Serial.print(" "); Serial.print(sudoku[d][4]); Serial.print(sudoku[d][5]); Serial.print(sudoku[d][6]); Serial.print(sudoku[d][7]); Serial.print(sudoku[d][8]); Serial.print(sudoku[d][9]); Serial.print(sudoku[d][10]); Serial.print(sudoku[d][11]); Serial.println(sudoku[d][12]); } */

}

108) Arduino DIY Math Solving Alarm Clock Out of Cardboard

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

DFRobot I2C 16x2 Arduino LCD Display Module

×

1

×

1

×

1

×

1

×

1

×

1

×

1

×

1

Buzzer

IR receiver (generic) JustBoom IR Remote

Seeed Pi RTC (DS1307)

Jumper wires (generic)

Resistor 10k ohm

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT This clock only works for the Elegoo remote as shown below:

Story

Have you ever fallen right back to sleep after snoozing your alarm clock? That's because you're still bran-dead when you hit that snooze button. A simple way to prevent this is to wake your brain up with a simple math problem. Earlier this year, I bought the Elegoo Starter Kit UNO R3 Project with the hope of being able to make some cool stuff that I once saw like robot or toy car. This is one of my very first project using Arduino Uno R3 and since I've just started it, the clock itself looks like crap. But it's still better than nothing, right? Link to the kit is here. Libraries For this little project, there's a few libraries you need to download and format as you can see below: https://github.com/z3t0/Arduino-IRremote. *For the IRremote library, you'll have to go to boarddefs.h, find the following segment of code: // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc // ATmega48, ATmega88, ATmega168, ATmega328 //#define IR_USE_TIMER1 // tx = pin 9 #define IR_USE_TIMER2 // tx = pin 3 and change it to: // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc // ATmega48, ATmega88, ATmega168, ATmega328 #define IR_USE_TIMER1 // tx = pin 9 //#define IR_USE_TIMER2 // tx = pin 3 https://github.com/arduino-libraries/LiquidCrystal https://github.com/adafruit/RTClib The cardboard box Choose and cut whatever cardboard that fits your circuit best. For me, I just cut a random amazon delivery box, and it works great!

The circuit Assemble your circuit according to the following image

To save some place because my goal is making an as small and compact an alarm clock as possible, I use the Arduino Prototype Shield v.5 that comes with the kit I bought. You can choose to use or not to use the board.

Fits perfectly! :)

Tips - When compiling the code, don't hit verify (the check icon) but hit upload (the arrow icon) instead. - When you upload, if you want the clock to have the right time on it, then don't unplug it from the computer or unplug after connect it to external battery. - If you unplug it and then connect it to the power source, the time shows is the time when you last upload it. Remote Controller + ST/REPT: Hit it if you want to set Alarm. If you've entered "Set hour," hit it again to set minute and again to set second. Hit it one last time to finish setting up alarm

+ The red power button: This button is programmed as a backspace button. Hit it once you've finished setting alarm and want to change (since this remote is a really crappy one, hit power button multiple times until the second line of the LCD indicating the alarm turns off), or when you're typing the wrong answer for the simple math problem (hit it until the answer turns into zero) + Apart from number buttons, ST/REPT and red power button, other buttons have no use. SCHEMATICS

CODE #include #include #include #include "RTClib.h" /** * Go to boarddefs.h * // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc * #else * #define IR_USE_TIMER1 tx = pin 9 * //#define IR_USE_TIMER2 // tx = pin 3 */ #include RTC_DS1307 rtc; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const int buzzerPin = 10; int RECV_PIN = 9; IRrecv irrecv(RECV_PIN); decode_results results; long num[10] = {0xFF6897, 0xFF30CF, 0xFF18E7, 0xFF7A85, 0xFF10EF, 0xFF38C7, 0xFF5AA5, 0xFF42BD, 0xFF4AB5, 0xFF52AD}; int a = 0; int b = 0; int c = 0; int d = 0; int setAlarm = 0;

void setup() { lcd.begin(16, 2); Serial.begin(9600); irrecv.enableIRIn();

if(rtc.begin()&&rtc.isrunning()){ rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } } void loop() { DateTime now = rtc.now(); lcd.setCursor(0, 0); if(now.hour() AC current sensor => AC voltage sensor => SDA output for LCD => SCL output for LCD => zero-cross detection

- pin 3 (numeric 3) => output to a LED which indicate pwm - pin 4 (numeric 4) => input from push-button "entry" - pin 5 (numeric 5) => input from push-button "+" - pin 6 (numeric 6) => input from push-button "-" - pin 10 (numeric 10) => pwm output that drives the Triac - pin 11 (numeric 11) => output to load shedding - pin 13 (numeric 13) => overflow LED alarm */ #include #include // documentation: https://tushev.org/articles/arduino/5/arduino-andwatchdog-timer #include // library to install: http://www.arduino.cc/playground/Code/Timer1 #include // https://github.com/fdebrabander/ArduinoLiquidCrystal-I2C-library // calibration variables: bool CALIBRATION = false; // if true = adjustment of Vcalibration and Icalibration bool VERBOSE = false; // if true = console display BUT VERY SLOW // Calibration of measures which depend of the hardware. Must be done once at the beginning : // first: ajust Vcalibration for reading 230V on the console // after: Icalibration by comparing with a multimeter // optional: phasecalibration can be adjust with the help of a powermeter float Vcalibration = 0.97; // to obtain 230V float Icalibration = 40.6; // to adjust the current reading to reality float phasecalibration = 1.7; // to correct the phase shift due to hardware byte totalCount = 20; // number of half-period studied measuring cycle // power thresholds in Watts int limitP = 1; // hysteresis of tolerance for the Triac action: if 1 => sensibility is +1W/-1W int delestON = 1; // threshold to start the load shedding int delestOFF = 350; // value to stop the load shedding bool etat_delest_repos = HIGH; // inactive state of the load shedding: HIGH for switched on // Reactance level to calculate dimstep : // dimstep evoluates by the factor 'power to dissiate'/reactancelevel // it is a compromise between reaction speed and instability:

// too small = instability risk, too high = slower // help how to calculate: reactancelevel ~ (dissipation power of the load in Watts)/40 unsigned int reactancelevel = 9; // Arduino inputs and outputs const byte pushEntryPin = 4; // push button 'entry' const byte pushPlusPin = 5; // push button '+' const byte pushMinusPin = 6; // push button '-' const byte triacPin = 10; // pwm output to Triac gate const byte delestPin = 11; // output for load shedding const byte triacLedPin = 3; // LED display Triac activity const byte limitLedPin = 13; // LED for power overflow const byte voltageSensorPin = 1; // input from voltage sensor const byte currentSensorPin = 0; // input from current sensor const byte zeroCrossPin = 2; // input from zero-cross detection // variables for interruptions (zero-crossing) : byte dimmax = 128; // max value of dim that shuttoff the Triac byte dim = dimmax; // Dimming level (0-128) 0 = on, 128 = 0ff char periodStep = 75; // value of the timer (65 for 60Hz, 78 for 50Hz, in s) // according the formula (500000/AC_freq)/NumSteps = periodStep // 78*128=10ms=1/2 period 50Hz but in fact 75 works better volatile int i = 0; // Variable to use as a counter volatile bool zero_cross = false; // zero-cross detected for driving the Triac volatile bool zero_cross_flag = false; // zero-cross detected for power calcultion // variables for electrical mesasures int readV, memo_readV, readI; // voltage and current in bits (0 1023 bits) float rPower, V, I, sqV, sumV = 0, sqI, sumI = 0, instP, sumP = 0; byte zero_crossCount = 0; // halp-period counter // other variables int dimstep; // value of the increment of dim unsigned long loadsheddingcounter; // time counter of load shedding duration unsigned int memo_temps = 0; bool delestage = false; // load shedding state bool unefois = false; // for one time only flag bool etat_delest_actif = !etat_delest_repos; // active loads shedding state byte ret_push_button = 0; byte windows = 0; byte count_before_timeout = 0;

byte refresh_tempo = 2; byte timeout = 20; // LCD declaration with I2C : // documentation : http://arduino-info.wikispaces.com/LCD-Blue-I2C // Set the pins on the I2C chip used for LCD connections: // addr, en,rw,rs,d4,d5,d6,d7,bl,blpol LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // => pinup for I2C with l'Arduino Uno R3 : SDA = A4, SCL = A5

// // SETUP //_____________________________________________________________________________________ void setup() { // Begin setup pinMode(pushEntryPin, INPUT_PULLUP); // set the push-buttons as entries pullup to +5V pinMode(pushPlusPin, INPUT_PULLUP); pinMode(pushMinusPin, INPUT_PULLUP); pinMode(triacPin, OUTPUT); // Set the Triac pin as output pinMode(delestPin, OUTPUT); pinMode(triacLedPin, OUTPUT); // Set the LED pin as output pinMode(limitLedPin, OUTPUT); attachInterrupt(digitalPinToInterrupt(zeroCrossPin), zero_cross_detect, RISING); // each zeroCrossPin rising generates an interruption : the function 'zero_cross_detect()' is called // documentation : https://www.arduino.cc/reference/en/language/functions/externalinterrupts/attachinterrupt/ Timer1.initialize(periodStep); // TimerOne from library initialisation Timer1.attachInterrupt(dim_check, periodStep); // for every periodStep time spent, dim_check is called // EEPROM functions are used to calculate how many time the device has rebooted // EEPROM stored values are of type char. // default values in case of first use are set to 255 unsigned char reboot_high = EEPROM.read(0); // to get the high value of the number unsigned char reboot_low = EEPROM.read(1); // to get the low value of the number unsigned int reboot = (reboot_high = totalCount ) zero_crossCount = 0; // as most as possible number of measures between the totalCount number of half-periods // themself defined by zero-cross flag while( zero_crossCount < totalCount ) { if( zero_cross_flag == true ) { // increment of half-period count for each zero-cross zero_cross_flag = false; zero_crossCount++; } numberOfSamples++; // number of measures memo_readV = readV; // memorize the past value readV = analogRead(voltageSensorPin); // voltage measure in bits - 0V = bit 512 delayMicroseconds(50); if( readV == memo_readV && readV > 509 && readV < 515 ) { // test if no grid lcd.setCursor(0, 0); lcd.print("ABSENCE DE "); lcd.setCursor(0, 1); lcd.print("TENSION SECTEUR "); delay(200); goto nogrid; // exit to the end of program } readI = analogRead(currentSensorPin); // current measure in bits - 0A = bit 512 delayMicroseconds(50); // calculation of the effective values of voltage and current if( CALIBRATION == true ) { // for calibration only sqV= (readV -512.0) * (readV -512.0); // -512 as offset to get 0V = bit 0 sumV += sqV; sqI = (readI -512.0) * (readI -512.0); sumI += sqI; } // end test upon CALIBRATION // instant power calculation instP = ((memo_readV -512.0) + phasecalibration * ((readV -512.0) - (memo_readV -512))) * (readI -512.0); sumP +=instP; } // End of while upon zero_crossCount // memorization of the values if( numberOfSamples > 0 ) { if( CALIBRATION == true ) { V = Vcalibration * sqrt(sumV / numberOfSamples);

I = Icalibration * sqrt(sumI / numberOfSamples); } rPower = ((Vcalibration * Icalibration * sumP )/ numberOfSamples) / 1000.0; }

// 2nd part: dim and dimstep calculation to drive the Triac, and load shedding management //_____________________________________________________________________________________ // // dimstep calculation: higher is the power to take in charge, higher will be dimstep if( rPower > 0 ) { dimstep = rPower/10/reactancelevel + 1; } else { dimstep = 1 - rPower/10/reactancelevel; } if( rPower > limitP ) { // injection increases, the delay to fire the Triac decreases if( dim > dimstep ) dim -= dimstep; else dim = 0; } else if( rPower < -limitP ) { // injection decreases, the delay to fire the Triac decreases if( dim + dimstep < dimmax ) dim += dimstep; else dim = dimmax; } if( dim < 1 ) digitalWrite(limitLedPin, HIGH); else { digitalWrite(limitLedPin, LOW); } analogWrite(triacLedPin, dimmax-dim); // load shedding management if( rPower > -delestON) { delestage = true; } shedding

// overload LED // Write the value to the LED for testing

// threshold activation value for load

if( delestage == true ) { if( unefois == false ) { digitalWrite(delestPin, etat_delest_actif); // load shedding driver update loadsheddingcounter = temps_actuel; // for load shedding spent time unefois = true; } if( rPower < -delestOFF ) { // threshold inactive value for load shedding digitalWrite(delestPin, etat_delest_repos); // load shedding driver update unefois = false; delestage = false; } } // end of test upon delestON // LCD and menues management //_______________________________________________ // // display update and push-button request every 2 seconds if( temps_actuel >= memo_temps + refresh_tempo ) {

memo_temps = temps_actuel; ret_push_button = push_button(); // reading push-button status here only lcd.clear(); lcd.setCursor(0, 0); if( ret_push_button == 1 ) next_windows(); // if 'entry' pushed increase of window if( windows == 0 ) { lcd.print("P= "); lcd.print(String(-rPower,0)); lcd.print("w"); lcd.setCursor(10, 0); lcd.print("T= "); lcd.print( map(dim, 0, dimmax, 99, 0) ); lcd.print("%"); lcd.setCursor(0, 1); lcd.print("DELESTAGE "); // load shedding in French if( delestage == true ) { lcd.print(temps_actuel - loadsheddingcounter); lcd.print("s "); } else { lcd.print("ARRETE"); } // stoped in French } else { // end of window 0, start of parameters review count_before_timeout++; if( count_before_timeout > timeout ) { // timeout to return to usual display if no job done count_before_timeout = 0; windows = 0; lcd.noBacklight(); } if( windows == 1 ) { if(ret_push_button == 2) limitP++; // if "+" pushed if(ret_push_button == 3) limitP--; // if "-" pushed limitP = constrain(limitP, 1, 200); lcd.print("SEUIL DETECTION"); lcd.setCursor(0, 1); lcd.print("seuil = "); lcd.setCursor(8, 1); lcd.print(limitP); lcd.print("W"); } // end of windows 1 if( windows == 2 ) { if(ret_push_button == 2) delestON++; // if "+" pushed if(ret_push_button == 3) delestON--; // if "-" pushed delestON = constrain(delestON, 1, 50); lcd.print("DELESTAGE ACTIF"); lcd.setCursor(0, 1); lcd.print("seuil = ");

lcd.setCursor(8, 1); lcd.print(delestON); lcd.print("W"); } // end of windows 2 if( windows == 3 ) { if(ret_push_button == 2) delestOFF+= 50; // if "+" pushed if(ret_push_button == 3) delestOFF-= 50; // if "-" pushed delestOFF = constrain(delestOFF, 50, 10000); lcd.print("DELESTAGE ARRET"); lcd.setCursor(0, 1); lcd.print("seuil = "); lcd.setCursor(8, 1); lcd.print(delestOFF); lcd.print("W"); } // end of windows 3 if( windows == 4 ) { if( ret_push_button > 1 ) etat_delest_repos =! etat_delest_repos; etat_delest_actif =! etat_delest_repos; lcd.print("DELESTAGE :"); lcd.setCursor(0, 1); if( etat_delest_repos == HIGH ) lcd.print("DEMARRE au repos"); else lcd.print("ARRETE au repos"); } // end of windows 4 if( windows == 5 ) { if(ret_push_button == 2) reactancelevel++; // if "+" pushed if(ret_push_button == 3) reactancelevel--; // if "-" pushed reactancelevel = constrain(reactancelevel, 1, 254); lcd.print("COEF DE REACTION"); lcd.setCursor(0, 1); lcd.print("taux = "); lcd.setCursor(7, 1); lcd.print(reactancelevel); } // end of windows 5 if( windows == 6 ) { byte phasecalibrationDEC = phasecalibration*10; if(ret_push_button == 2) phasecalibrationDEC++; // if "+" pushed if(ret_push_button == 3) phasecalibrationDEC--; // if "-" pushed phasecalibrationDEC = constrain(phasecalibrationDEC, 1, 30); phasecalibration = phasecalibrationDEC/10.0; lcd.print("CALIBRATION Pu"); lcd.setCursor(0, 1); lcd.print("valeur = "); lcd.setCursor(9, 1); lcd.print(phasecalibration); } // end of windows 6

// EEPROM updated if needed EEPROM.update(2, limitP); EEPROM.update(3, delestON); EEPROM.update(4, highByte(delestOFF)); EEPROM.update(5, lowByte(delestOFF)); EEPROM.update(6, etat_delest_repos); EEPROM.update(7, reactancelevel); EEPROM.update(8, (phasecalibration*10)); } // end of paramerter review } // end of display management // console display if( CALIBRATION == true ) { Serial.print(V); Serial.print(" | "); Serial.print(I/1000); Serial.print(" | "); Serial.print(rPower); Serial.println(); } if( VERBOSE == true ) { Serial.print(rPower); Serial.print(" || "); Serial.print(dimstep); Serial.print(" | "); Serial.print(dim); Serial.print(" || "); Serial.print(" load shedding : "); Serial.print(delestage); Serial.print(" seconds : "); Serial.println(temps_actuel - loadsheddingcounter); } else delay(1); // required for stability nogrid: wdt_reset(); // watchdog reset }

// end of main Loop

// // NEXT_WINDOWS : next windows procedure //_____________________________________________________________________________________ void next_windows() { windows = (windows+1) % 7;

// next windows modulo 6

ret_push_button = 0; // reset the buttun state lcd.clear(); lcd.setCursor(0, 0); } // end of next_windows function

// // PUSH_BUTTON : return value depending of the state of the 3 push-buttons //_____________________________________________________________________________________ byte push_button() { if( digitalRead(pushEntryPin) == 0 ) { count_before_timeout = 0; // reset the timeout counter lcd.backlight(); // switch on display return 1; } if( digitalRead(pushPlusPin) == 0 ) { count_before_timeout = 0; // reset the timeout counter lcd.backlight(); // switch on display refresh_tempo = 1; // temporary lower display update duration return 2; } if( digitalRead(pushMinusPin) == 0 ) { count_before_timeout = 0; // reset the timeout counter lcd.backlight(); // switch on display refresh_tempo = 1; // temporary lower display update duration return 3; } refresh_tempo = 2; // go back to initial value return 0; } // end of push_button function

111) Arduino Serial to LANC

COMPONENTS AND SUPPLIES SparkFun Arduino Pro Mini 328 5V/16MHz

×

1

×

1

×

1

×

1

2.5mm stereo plug 5.1V Zener diode General Purpose Transistor NPN and two resistors

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT I was about to digitize a large collection of Hi8/Video8 tapes with my Sony TRV-120E camera. Some of the tapes were recorded in LP and had to be played in its original camcorder. I knew that the TRV-120E had surpassing capabilities and could digitize analog video input on the fly. However, on many European camcorders this functionality is locked due to tax reasons. After some research, I found old methods to fix it with LPT ports and DOS software by going into service mode. Since LPT ports are more rare than Pandas, I decide to renew the methods with an Arduino Mini Pro 16Mhz/5V. All the hardware you need is two resistors, a NPN transistor, 5.1V Zener diode and a 2.5mm stereo plug. The code communicates with the camera over the LANC protocol which is common for many Sony cameras. The code can also be used to remotely control the camera over a serial interface

SCHEMATICS

All the hardware you need for this project, you can skip the push button (not used). The NPN transistor can be almost any small-signal type.

CODE /* Arduino LANCRS232 interface For communicating with cameras via LANC For the interface circuit interface see "LANC" is a registered trademark of SONY. CANON calls their LANC compatible port "REMOTE".

-----------------------------------------------------------------------------------------Comments regarding service mode for Sony second generation D8 camcorders: DCR-TRV8000E, DCR-TRV8100E, DCR-TRV120E, DCR-TRV125E, DCR-TRV320E, DCR-TRV325E DCR-TRV420E, DCR-TRV520E, DCR-TRV620E, DCR-TRV725E LANC message layout when reading/writing EEPROM(8 bytes each sent with LSB first) B0 B1 B2 B3 B4 B5 B6 B7 B0 = First sent byte from our adapter B1 = Second sent byte from our adapter B2 B3 B4 = The 4 highest bits b7..b4 tells which page in the EEPROM you are at B5 = Confirmation that the command has been received, read command confirmed with F0h, write commands confirmed with F1h B6 = Tells which address in the EEPROM you are at B7 = Data at address The following commands is used to navigate the EEPROM and change data B1 B2 FFh 00h = Read command, tells you current page:address:data without changing anything FFh 67h = Increase page by 1 FFh 65h = Decrase page by 1 FFh 38h = Increase address by 1 FFh 36h = Decrase address by 1 FFh 34h = Increase data by 1 FFh 30h = Decrase data by 1 FFh 32h = STORE command Metod for checksums (PAGE:ADDRESS:DATA): 1) enable changes in memory: 00:01:00 to 00:01:01 (Store) 2) change data on page D, how You need (all with STORE). 3) read new value:

"xx" from 02:F0 "yy" from 02:F1 4) enable update and visibility of checksums on (0F:FE and 0F:FF): 00:FF:00 -> 00:FF:02 (STORE) 00:01:01 -> 00:01:80 (STORE) 5) update new checksums: write to address: 0F:FF data "xx" ( from 02:F0 ) (STORE) 0F:FE data "yy" ( from 02:F1 ) (STORE) 6) disable changes: 00:FF:02 -> 00:FF:00 (STORE) 00:01:80 -> 00:01:00 (STORE) Links to more information: http://lea.hamradio.si/~s51kq/DV-IN.HTM http://www.sps.volyne.cz/set1394/anin/code20.html -----------------------------------------------------------------------------------------*/ // The code uses fast I/O write because its time critical, // therefore setting pins are done by writing directly to the registers: #define cmdPinON (PORTD = B10000000) // Set digtal pin 7 (PD7) #define cmdPinOFF (PORTD = B00000000) // Reset digtal pin 7 (PD7) #define ledON (PORTB = B00100000) // Set LED pin 13 (PB5) #define ledOFF (PORTB = B00000000) // Reset LED pin 13 (PB5) #define lancPinREAD (PINB & B00001000) // Reads pin 11 (PB3) #define lancPin 11 int bitDura = 104; // Duration of one LANC bit in microseconds, orginal 104 int halfbitDura = 52; // Half of bitDura byte strPointer = 0; // Index when receiving chars char inString[5]; // A string to hold incoming data char outString[25]; // A string to hold outgoing data boolean strComplete = false; // Indicator to see if the string is complete boolean lancCmd[16]; // Array for the lancCmd in bits boolean lancMessage[64]; // Array for the complete LANC message in bits void setup() { DDRD = DDRD | B10000000; // Config cmdPin as output DDRB = DDRB & B11110111; // Config lancPin as input DDRB = DDRB | B00100000; // Config ledPin as output pinMode(lancPin, INPUT); // Listens to the LANC line, used for pulseIn function cmdPinOFF; // Reset LANC control pin so that the LANC line is unaffected(HIGH) Serial.begin(57600); // Start serial port

Serial.println("Welcome to the Arduino LANC-RS232 interface"); Serial.println("Send two bytes in hex form etc. 02AF and wait for reply from camera"); }

void loop() { if (strComplete) { // inString has arrived if (hexchartobitarray()) { // Convert hex chars to bitarray sendLanc(4); // The LANC command needs to be repeated 4 times bitarraytohexchar(); // Convert received bitarray to hex chars for (int i=0; i 1) { knobval = 1; delay (50); } setyeartemp=setyeartemp + knobval; if (setyeartemp < 2018) { //Year can't be older than currently, it's not a time machine. setyeartemp = 2018; } //itoa(setyeartemp - 2000, tmp_string, 10); // https://www.avrfreaks.net/forum/how-do-iprint-variable-u8glib itoa(setyeartemp, tmp_string, 10); // https://www.avrfreaks.net/forum/how-do-i-printvariable-u8glib u8g.firstPage(); do { u8g.drawStr( 0, 20, "Set Year"); // u8g.drawStr( 0, 40, "20"); u8g.drawStr(25, 40, tmp_string); } while( u8g.nextPage() );

setyear(); } int setmonth () { pushlength = pushlengthset; pushlength = getpushlength (); if (pushlength != pushlengthset) { return setmonthtemp; } // lcd.setCursor (0,1); knob.write(0); delay (50); knobval=knob.read(); if (knobval < -1) { knobval = -1; } if (knobval > 1) { knobval = 1; } setmonthtemp=setmonthtemp + knobval; if (setmonthtemp < 1) {// month must be between 1 and 12 setmonthtemp = 1; } if (setmonthtemp > 12) { setmonthtemp=12; } itoa(setmonthtemp, tmp_string, 10); u8g.firstPage(); do { u8g.drawStr( 0, 20, "Set Month"); u8g.drawStr(25, 40, tmp_string); } while( u8g.nextPage() ); setmonth(); }

int setday () { if (setmonthtemp == 4 || setmonthtemp == 5 || setmonthtemp == 9 || setmonthtemp == 11) { //30 days hath September, April June and November maxday = 30; } else { maxday = 31; //... all the others have 31 } if (setmonthtemp ==2 && setyeartemp % 4 ==0) { //... Except February alone, and that has

28 days clear, and 29 in a leap year. maxday = 29; } if (setmonthtemp ==2 && setyeartemp % 4 !=0) { maxday = 28; } pushlength = pushlengthset; pushlength = getpushlength (); if (pushlength != pushlengthset) { return setdaytemp; } knob.write(0); delay (50); knobval=knob.read(); if (knobval < -1) { knobval = -1; } if (knobval > 1) { knobval = 1; } setdaytemp = setdaytemp+ knobval; if (setdaytemp < 1) { setdaytemp = 1; } if (setdaytemp > maxday) { setdaytemp = maxday; } itoa(setdaytemp, tmp_string, 10); u8g.firstPage(); do { u8g.drawStr( 0, 20, "Set Day"); u8g.drawStr(25, 40, tmp_string); } while( u8g.nextPage() ); setday(); }

int setzi () { pushlength = pushlengthset; pushlength = getpushlength (); if (pushlength != pushlengthset) { return setzitemp; } knob.write(0); delay (50); knobval=knob.read();

if (knobval < -1) { knobval = -1; } if (knobval > 1) { knobval = 1; } setzitemp=setzitemp + knobval; if (setzitemp < 0) {// month must be between 0 and 6 setzitemp = 0; } if (setzitemp > 6) { setzitemp=6; } itoa(setzitemp, tmp_string, 10); u8g.firstPage(); do { u8g.drawStr( 0, 20, "Set Day of Week"); u8g.drawStr(25, 40, tmp_string); u8g.drawStr(0,60, daysOfTheWeek[setzitemp]); } while( u8g.nextPage() ); setzi(); } int setore () { pushlength = pushlengthset; pushlength = getpushlength (); if (pushlength != pushlengthset) { return setoretemp; } knob.write(0); delay (50); knobval=knob.read(); if (knobval < -1) { knobval = -1; delay (50); } if (knobval > 1) { knobval = 1; delay (50); } setoretemp=setoretemp + knobval; if (setoretemp < 0) { setoretemp = 0; } if (setoretemp > 23) { setoretemp=23;

} itoa(setoretemp, tmp_string, 10); u8g.firstPage(); do { u8g.drawStr( 0, 20, "Set Hour"); u8g.drawStr(25, 40, tmp_string); } while( u8g.nextPage() ); setore(); } int setmins () { pushlength = pushlengthset; pushlength = getpushlength (); if (pushlength != pushlengthset) { return setminstemp; } knob.write(0); delay (50); knobval=knob.read(); if (knobval < -1) { knobval = -1; delay (50); } if (knobval > 1) { knobval = 1; delay (50); } setminstemp=setminstemp + knobval; if (setminstemp < 0) { setminstemp = 0; } if (setminstemp > 59) { setminstemp=59; } itoa(setminstemp, tmp_string, 10); u8g.firstPage(); do { u8g.drawStr( 0, 20, "Set Minutes"); u8g.drawStr(25, 40, tmp_string); } while( u8g.nextPage() ); setmins(); } // see https://arduino.cz/tutorial-uzivani-hodin-realneho-casu-ds1307-a-ds3231-s-arduinem/ // http://tronixstuff.com/2014/12/01/tutorial-using-ds1307-and-ds3231-real-time-clockmodules-with-arduino/

118) Arduino Alarm Clock projet

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

Adafruit Standard LCD - 16x2 White on Blue

×

1

×

1

×

1

×

1

×

1

×

1

×

1

Buzzer

Thermistor DS3231 RTC Module Jumper wires (generic)

Potentiometer (10K)

NECESSARY TOOLS AND MACHINES 3D Printer (generic)

ABOUT THIS PROJECT Design Tools Inventor Information Snap Together Case for an Arduino Uno Alarm Clock with date and temperature display. Parts List (Required) (All electrical components found in an Elegoo "Most Complete Starter Kit") Arduino Uno LCD 1602 Module DS3231 RTC Active Buzzer Potentiometer (10K) Thermistor Dupont Wires 3D Printed Parts (4) Parts (optional) Thermistor - The DS3231 has a built in temperature reading device,

but it is used more as an internal temperature reading and takes about a minute to update when temp changes. Libraries Makuna Rtc #include //Library for RTC Make sure you use this same library otherwise aspects of the code will cause an error! -------------------------------------------------------------------------------#include //Allows comunication with TWI (Two Wire Interface) #include //Used for DS3231 and thermister LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Pins used by the LCD Additional Information Code can be found on Thingiverse with Files. To fellow Americans...The Date displays dd/mm/yyyy TemperatureCan be displayed in Celcius by removing conversion in code. Soon to come.. Replacement knob for Potentiometer. Way to use the reset button for turning off alarm.. (would appreciate help from code ninjas) SCHEMATICS

CODE /* Project: Use DS3231 RTC to print Time, Date.. Use Thermistor for temp.

Ability to set Alarm. */ //----------------------------------------------------------------------------// Define variables. #include //Library for RTC #include //Allows comunication with TWI (Two Wire Interface) #include //Used for DS3231 and thermister LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Pins used by the LCD DS3231 rtc(SDA, SCL); Time t; #define buz 11 int tempPin = 0; int Hor; int Min;

int Sec; int tempC; int tempF; int tempCDS3231; int tempFDS3231;

//------------------------------------------------------------------------// Used to fix Date, Time, Day of Week // Uncomment to adjust. Be sure to // back once fixed. //rtc.setDOW(WEDNESDAY); //rtc.setTime(01, 33, 00);

// Set Day-of-Week to SUNDAY

// Set the time to 12:00:00 (24hr format)

//rtc.setDate(23, 8, 2018); // Set the date to August 8th, 2018 //--------------------------------------------------------------------------

void setup() {

Wire.begin(); rtc.begin(); Serial.begin(9600); pinMode(buz, OUTPUT); lcd.begin(16,2); lcd.setCursor(0,0); t = rtc.getTime(); Hor = t.hour; Min = t.min; Sec = t.sec;

}

//---------------------------------------------------------------------

void loop() { int tempReading = analogRead(tempPin); // This is OK double tempK = log(10000.0 * ((1024.0 / tempReading - 1))); tempK = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * tempK * tempK )) * tempK ); // Temp Kelvin int tempC = tempK - 273.15;

// Convert Kelvin to Celcius

int tempF = (tempC * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit //-----------------------------------------------------------------------------------------//Can change the ABOVE tempC and tempF "int" to "float" this can give you temperatures with two decimal points. //Can also use "lcd.print(tempF, 1);" BELOW to print with one decimal place or "lcd.print(tempF, 0);" // print without decimal place //-----------------------------------------------------------------------------------------lcd.setCursor(0,0); //Top line of the LCD lcd.print("

");

lcd.print(rtc.getTimeStr()); lcd.print("

");

lcd.setCursor(0,1); lcd.print("

");

lcd.print(rtc.getDateStr());

//---------------------------------------------------------lcd.setCursor(0,1); //Second line of the LCD tempFDS3231 = (tempCDS3231 * 1.8) + 32.0; // Convert C to F tempCDS3231 = (rtc.getTemp()); lcd.setCursor(0,1); lcd.print(tempF); lcd.print((char)223); //This creates a Degree symbol lcd.print("F "); lcd.print(rtc.getDateStr());

//-------------------------------------------------------------------------t = rtc.getTime(); Hor = t.hour; Min = t.min; Sec = t.sec;

//-----------------------------------------------------------------------------------------//Use the BELOW "if" statement to set your desired alarm time if( Hor == 10 && (Min == 00 || Min == 00)) //Comparing the current time with the Alarm time //-----------------------------------------------------------------------------------------{ Buzzer(); Buzzer(); lcd.clear(); lcd.print("Alarm ON"); lcd.setCursor(0,1); lcd.print("Wake Up!!"); Buzzer(); Buzzer();

}

delay(1000); }

void Buzzer() { digitalWrite(buz,HIGH); delay(500); digitalWrite(buz, LOW); delay(500);

}

119) Plant Watering Alarm System with Arduino projet

COMPONENTS AND SUPPLIES Arduino Nano R3

SparkFun Soil Moisture Sensor (with Screw Terminals)

×

1

×

1

LED (generic) ×

1

×

1

×

1

×

2

×

1

×

1

Buzzer

Servos (Tower Pro MG996R) Resistor 221 ohm

Jumper wires (generic)

AA Batteries

NECESSARY TOOLS AND MACHINES Hot glue gun (generic)

Soldering iron (generic)

APPS AND ONLINE SERVICES Arduino IDE

Ardublockly

ABOUT THIS PROJECT A device that warns us with light sound and a sign when our plan needs water. The project was made by the students of the “Little Hackers” evening club of the Experimental Elementary School of Florina. The device contains a moisture sensor, a servo motor a led light and a buzzer.

The moisture sensor is placed the plant pot and continuesly reads the moisture values. When that values fall under a certain limit the device warns us by: Blinking the led light Sending a beeping sound from the buzzer Turning the small sign so that the “No water” sketch is shown

The final project was presented along with other projects from students of all schools of Florina at the 7th Students Festival for Digital Creations

SCHEMATICS

CODE #include Servo myServo; //The sign servo int buzzerPin = 8; //The Buzzer pin int redLed = 9; //The led pin int moisture; //The moisture value void setup() { pinMode(buzzerPin,OUTPUT); pinMode(redLed,OUTPUT); myServo.attach(11; } void loop() { moisture = analogRead(A0); //Read the moisture from sensor moisture = map(moisture,0,1023,100,1); //Map the moisture values to 1-100. if (moisture < 50) { //If moisture is low myServo.write(165); //Turn motor to "No water" sign digitalWrite(redLed,HIGH); //Turn on the led light tone(buzzerPin, 2000, 500); //Play a buzzer tone for halph a second delay(1000); //delay for a second digitalWrite(redLed,LOW); //Turn off the led light delay(1000); //Delay another second } else { //If moisture is OK digitalWrite(redLed,HIGH); //Just turn on the led light myServo.write(20); //and turn motor to "plant ok" sign } }

120) Arduino Light Follower Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

mini breadboard - mixed colours

×

1

×

1

×

1

×

1

×

1

×

1

10 jumper wires 200mm male 5 LDR 10 10k 1/4w resistor Analog 180° Micro Servo 4mm cardboard

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT 1. How does it Work? The choice to go up or down in order to follow the light is done in a very simple way. There are four LDR two up and two down. Arduino reads the analog value of all LDR, if the average of the two upper values is greater than the two lower the light is up so the angle of the microservo is incremented otherwise decremented. 2. A Little Clarification Since the average is not a fixed number, as you can see in the code, a threshold is used. In this way the angle is changed if and only if the two averages are widely different. const int threshold = 50; [.....] down_average = (A0_val + A1_val)/2; up_average = (A2_val + A3_val)/2; diff = abs(up_average-down_average); if ((up_average > down_average) && (diff > threshold)) { if (val < 180) //if different from max val { val++;

myservo.write(val); } } if((down_average > up_average) && (diff > threshold)) { if (val > 0) //if different from min val { val--; myservo.write(val); } } 3. The Circuit Make the circuit below!

4. Print & Cut Download the attached file, print it, glue it on the cardboard and cut all the pieces for yours light follower. You should obtain something like this.

5. Mount the Base Mount the breadboard base in this way. Glue it if necessary.

6. Mount the Servo Mount the servo like below. Screw it for more stability.

7. Mount the Bracket Mount the bracket in this way.

8. Mount the Servo Gear Mount the servo gear. Screw it in this way.

9. Put all Together Put all together. You should obtain something like this

10. Glue the Breadboard on the Base Glue the breadboard on the base. You can use the biadhesive tape of the breadboard.

11. Screw Arduino Screw Arduino on the back of the base.

12. Well Done Well done. Now you have all the necessary. Download the code on your Arduino and enjoy with your light follower!

SCHEMATICS

CODE #include Servo myservo; int up_average; int down_average; int A0_val; int A1_val; int A2_val; int A3_val; int val = 90;

int diff; const int threshold = 50; void setup() { pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); myservo.attach(11); myservo.write(val); } void loop() { A0_val = analogRead(A0); //reading data from sensors A1_val = analogRead(A1); A2_val = analogRead(A2); A3_val = analogRead(A3); down_average = (A0_val + A1_val)/2; //the sum of the two lower sensors /2 up_average = (A2_val + A3_val)/2; //the sum of the two upper sensors /2 diff = abs(up_average-down_average); //checking the difference between the two averages if ((up_average > down_average) && (diff > threshold)) { if (val < 180) //if different from max val { val++; myservo.write(val); } } if((down_average > up_average) && (diff > threshold)) { if (val > 0) //if different from min val { val--; myservo.write(val); } } delay(25); }

121) Arduino More than an Hour Timer Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

1

×

1

Breadboard (generic)

Resistor 10k ohm

Resistor 221 ohm ×

3

×

1

×

1

×

1

×

1

×

3

General Purpose Transistor NPN

Buzzer

Tactile Button Jumper wires (generic)

LED (generic)

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT Introduction

I was in need of an Hour timer that could be started and stopped with a press of a button. When I got to building and coding it I thought that I could do more than a simple hour timer. I cobbled together a timer that has a range from 1 minute to an hour and a half and still only uses 1 button to control it. I didn’t want to use an Arduino for the final product but still prototyped it on the Arduino. I used an ATTINY85 for the final product.

Parts Required

3 x 220 OHM resistors 1 x 10k Resistor 1 x NPN Transistor 3 x LED's A Piezo Buzzer A Button Some Jumper Wires A breadboard and An Arduino The Code I've used a lot defines to make the program more readable. The “defines’ don't use any memory other than the actual value itself. I have also used preprocessor directives so I can use the same sketch on an Arduino and the ATTiny85. // LOTS OF DEFINES TO KEEP THINGS EASY TO READ AND

SAVE SPACE #define DEVICE ARDUINO

// ARDUINO or ATTINY85

#define COMMON_PIN_ANODE 1 // 1 = Common Anode; 0 = Common Cathode #define ATTINY85 1 #define ARDUINO 0 #define SWITCH_OFF_LENGTH 3 #if DEVICE //ATTINY85 INCLUDES & DEFINES #include #include #define LED1 0 #define LED2 1 #define LED3 2 #define BUTTON 3 #define BUZZER 4 #else #define LED1 11 #define LED2 12 #define LED3 13 #define BUTTON 2 #define BUZZER 6 #endif // PROGRAM STATES #define CHOOSETIMER 1 #define COUNTDOWN 2 #define BUZZ

3

// BUTTON STATES #define NO_PRESS 0 #define SHORT_PRESS 1 #define LONG_PRESS 2 #define OFF_PRESS 3 The times array holds the seconds that can be selected for the countdown. Feel free to change these to the times you would use most often. Mine are set to 1 min, 5 min, 15 min, 30 min, 45min, 1 hour and 1 hour 30 mins. // VARIABLES WOOP! unsigned long timer = 0; byte MODE = 2; byte cdMenu = 1; int countDown = 45; int times[] = {0, 60, 300,

900,

1800, 2700, 3600, 5400};

The function Sleep will: Beep 3 times when switching off, Twice when switching on. It will put the ATTINY85 into low power mode or Emulate the way the ATTINY will sleep when prototyping on the Arduino. There are 2 sleep functions, one for the arduino and one for the AtTiny85 #if DEVICE void sleep () { // with compliments of https://bigdanzblog.wordpress.com/2014/08/10/attiny85-wake-from-sleepon-pin-state-change-code-example/ delay(500); beep(); delay(200); beep(); delay(200);

// BUTTON DEBOUNCE (LONG)

beep(); countDown = times[cdMenu]; // RESET TIMER READY FOR WHEN YOU COME BACK FROM SLEEPING MODE = COUNTDOWN; // GETTING READY FOR WHEN YOU COME BACK FROM SLEEPING GIMSK |= _BV(PCIE);

// Enable Pin Change Interrupts

PCMSK |= _BV(BUTTON); ADCSRA &= ~_BV(ADEN);

// Use PB3 as interrupt pin // ADC off

set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement sleep_enable(); Register (SE BIT) sei();

// Sets the Sleep Enable bit in the MCUCR // Enable interrupts

sleep_cpu(); cli();

// sleep // Disable interrupts

PCMSK &= ~_BV(BUTTON); sleep_disable();

// Clear SE bit

ADCSRA |= _BV(ADEN); sei();

// Turn off PB3 as interrupt pin // ADC on

// Enable interrupts

beep(); delay(200); beep(); } ISR(PCINT0_vect) {} #else void sleep () { delay(500); // BUTTON DEBOUNCE (LONG) beep(); delay(200); beep(); delay(200);

beep(); countDown = times[cdMenu]; // RESET TIMER READY FOR WHEN YOU COME BACK FROM SLEEPING MODE = COUNTDOWN; // GETTING READY FOR WHEN YOU COME BACK FROM SLEEPING // EMULATES THE SLEEPING WHEN USING THE ARDUIN (IT SAVES NO POWER) while (digitalRead(BUTTON)); beep(); delay(200); beep(); } #endif The beep function beeps. // SELF EXPLANATORY void beep() { digitalWrite(BUZZER, HIGH); delay(30); digitalWrite(BUZZER, LOW); } The “clearDisplay”, “displayTime” and “displayCountDownTime” functions control the 3 LED's on or off states. I've also included preprocessor directives in these functions to easily choose between whether I’m using common anode or common cathode for the LED's. // SETS ALL LED's PINS TO LOW OR HIGH DEPENDING ON THE LED's COMMON PIN CONNECTION void clearDisplay() { byte leds = 0;

#if COMMON_PIN_ANODE digitalWrite(LED1, !bitRead(leds, 0)); digitalWrite(LED2, !bitRead(leds, 1)); digitalWrite(LED3, !bitRead(leds, 2)); #else digitalWrite(LED1, bitRead(leds, 0)); digitalWrite(LED2, bitRead(leds, 1)); digitalWrite(LED3, bitRead(leds, 2)); #endif } // SHOW THE TIME SELECTED void displayTime() { int leds = 0; // GET THE INDEX IN THE ARRAY FROM THE countDown VALUE for (int t = 0; t < 8; t++) { if (countDown >= times[t]) { leds = t; } } #if COMMON_PIN_ANODE digitalWrite(LED1, !bitRead(leds, 0)); digitalWrite(LED2, !bitRead(leds, 1)); digitalWrite(LED3, !bitRead(leds, 2)); #else digitalWrite(LED1, bitRead(leds, 0)); digitalWrite(LED2, bitRead(leds, 1)); digitalWrite(LED3, bitRead(leds, 2));

#endif } // SHOW THE CURRENT COUNT DOWN (ROUNDED UP) void displayCountDownTime() { int leds = 0; for (int t = 0; t < 8; t++) { if (countDown >= times[t]) { leds = t + 1; } } #if COMMON_PIN_ANODE digitalWrite(LED1, !bitRead(leds, 0)); digitalWrite(LED2, !bitRead(leds, 1)); digitalWrite(LED3, !bitRead(leds, 2)); #else digitalWrite(LED1, bitRead(leds, 0)); digitalWrite(LED2, bitRead(leds, 1)); digitalWrite(LED3, bitRead(leds, 2)); #endif } The “buttonCheck” function is called on every loop of the Loop function: Checks if the button is pressed, how long it is pressed and returns whether it was pressed quickly, long or extremely long. This function is the interface between the code and the real world. It plays a huge function in the program and it took a long time to make it feel just right.

// FINDS OUT THE BUTTON STATES byte buttonCheck() { clearDisplay(); int butLength = NO_PRESS; int mybut = digitalRead(BUTTON); if (!mybut) { // START TIMING unsigned long timerButton = millis() / 10; beep(); // LOOP HERE WHILE THE BUTTON IS DOWN CONTINUING TO TIME while (!mybut) { mybut = digitalRead(BUTTON); // BLINK RANDOMLY WHEN THE TIMER VALUE IS LONGER THAN THE SET VALUE FOR THE SWITCH OFF if ((millis() / 10 - timerButton) > (SWITCH_OFF_LENGTH * 100)) { digitalWrite(LED1, bitRead(millis() / 100, 0)); digitalWrite(LED2, bitRead(millis() / 100, 1)); digitalWrite(LED3, bitRead(millis() / 100, 2)); } } clearDisplay(); // DECIDE WHAT TO RETURN DEPENDING ON HOW LONG THE BUTTON WAS HELD IN if ((millis() / 10 - timerButton) > 75) { butLength = LONG_PRESS; } else {

butLength = SHORT_PRESS; } if ((millis() / 10 - timerButton) > (SWITCH_OFF_LENGTH * 100)) { butLength = OFF_PRESS; } delay(50); PRESS

// SORT OF DEBOUNCING THE BUTTON

} return butLength; } I set up the pins in the SETUP function void setup() { pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); pinMode(BUZZER, OUTPUT); pinMode(BUTTON, INPUT_PULLUP); timer = (millis() / 100); clearDisplay(); } In the Loop function I check the button state then decide what mode the program should go into. Either choosing the timer value, counting down or switching off. It’s a bit all over the place but it works. When the program has counted down to 0 it buzzes. void loop() { int button = buttonCheck(); switch (button) {

case LONG_PRESS: // CYCLE THROUGH THE MODES MODE++; if (MODE >= BUZZ) { MODE = CHOOSETIMER; } break; case OFF_PRESS: sleep(); button = NO_PRESS; // FORCE THE BUTTON TO NO_PRESS (I CAN'T REMEMBER WHY THOUGH) break; } switch (MODE) { case CHOOSETIMER: countDown = times[cdMenu]; FROM THE ARRAY OF TIMES if (button == SHORT_PRESS) {

// SET THE COUNT DOWN TIME // CYCLE TIMES

cdMenu++; if (cdMenu == 8) { cdMenu = 1; // skip 0 value in the array } countDown = times[cdMenu]; } displayTime(); break; case COUNTDOWN:

//EVERY SECCOND FLASH YOUR REMAINING TIME (ROUNDING UP) AND COUNT DOWN if (((millis() / 100) - timer) >= 10) { timer = (millis() / 100); displayCountDownTime(); delay(50); clearDisplay(); countDown--; } // WHEN THE COUNTDOWN IS UP BUZZ!!!!! if (countDown = times[t]) { leds = t; } } #if COMMON_PIN_ANODE digitalWrite(LED1, !bitRead(leds, 0)); digitalWrite(LED2, !bitRead(leds, 1)); digitalWrite(LED3, !bitRead(leds, 2)); #else digitalWrite(LED1, bitRead(leds, 0)); digitalWrite(LED2, bitRead(leds, 1)); digitalWrite(LED3, bitRead(leds, 2)); #endif } // SHOW THE CURRENT COUNT DOWN (ROUNDED UP) void displayCountDownTime() {

int leds = 0; for (int t = 0; t < 8; t++) { if (countDown >= times[t]) { leds = t + 1; } } #if COMMON_PIN_ANODE digitalWrite(LED1, !bitRead(leds, 0)); digitalWrite(LED2, !bitRead(leds, 1)); digitalWrite(LED3, !bitRead(leds, 2)); #else digitalWrite(LED1, bitRead(leds, 0)); digitalWrite(LED2, bitRead(leds, 1)); digitalWrite(LED3, bitRead(leds, 2)); #endif } // FINDS OUT THE BUTTON STATES byte buttonCheck() { clearDisplay(); int butLength = NO_PRESS; int mybut = digitalRead(BUTTON); if (!mybut) { // START TIMING unsigned long timerButton = millis() / 10; beep(); // LOOP HERE WHILE THE BUTTON IS DOWN CONTINUING TO TIME while (!mybut) { mybut = digitalRead(BUTTON); // BLINK RANDOMLY WHEN THE TIMER VALUE IS LONGER THAN THE SET VALUE FOR THE SWITCH OFF if ((millis() / 10 - timerButton) > (SWITCH_OFF_LENGTH * 100)) { digitalWrite(LED1, bitRead(millis() / 100, 0)); digitalWrite(LED2, bitRead(millis() / 100, 1)); digitalWrite(LED3, bitRead(millis() / 100, 2)); } } clearDisplay(); // DECIDE WHAT TO RETURN DEPENDING ON HOW LONG THE BUTTON WAS HELD IN

if ((millis() / 10 - timerButton) > 75) { butLength = LONG_PRESS; } else { butLength = SHORT_PRESS; } if ((millis() / 10 - timerButton) > (SWITCH_OFF_LENGTH * 100)) { butLength = OFF_PRESS; } delay(50); // SORT OF DEBOUNCING THE BUTTON PRESS } return butLength; }

void setup() { pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); pinMode(BUZZER, OUTPUT); pinMode(BUTTON, INPUT_PULLUP); timer = (millis() / 100); clearDisplay(); } void loop() { int button = buttonCheck(); switch (button) { case LONG_PRESS: // CYCLE THROUGH THE MODES MODE++; if (MODE >= BUZZ) { MODE = CHOOSETIMER; } break; case OFF_PRESS: sleep(); button = NO_PRESS; // FORCE THE BUTTON TO NO_PRESS (I CAN'T REMEMBER WHY THOUGH) break; } switch (MODE) { case CHOOSETIMER: countDown = times[cdMenu];

// SET THE COUNT DOWN TIME FROM THE

ARRAY OF TIMES if (button == SHORT_PRESS) { // CYCLE TIMES cdMenu++; if (cdMenu == 8) { cdMenu = 1; // skip 0 value in the array } countDown = times[cdMenu]; } displayTime(); break; case COUNTDOWN: //EVERY SECCOND FLASH YOUR REMAINING TIME (ROUNDING UP) AND COUNT DOWN if (((millis() / 100) - timer) >= 10) { timer = (millis() / 100); displayCountDownTime(); delay(50); clearDisplay(); countDown--; } // WHEN THE COUNTDOWN IS UP BUZZ!!!!! if (countDown 900)

//Something is detected/ object has been stolen

{ digitalWrite(trig,HIGH); //trigger the camera delay(100); digitalWrite(trig,LOW); delay(1000);

// delay 1 sec_Take a picture in every second

} else { digitalWrite(trig,LOW);

} } 126) Arduino Scrolling Text Display Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

Digilent WS2812 Addressable LED Strip This wasn't the actual product used, but uses the same technology.

×

1

×

1

Digilent 5V 4000mA Switching Power Supply Again, this wasn't the actual product used, but serves the same purpose.

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT The Idea So I originally saw a project on here to make an LED coffee table, and read into it's workings and decided to buy some indexable (mappable) LEDs based on WS2812b to achieve this. I quickly laid them out in a grid layout 10x5 and began programming from scratch.

Front of original board

Rear of original board The Process After I got a few patterns going, I realised there was potential for it to display text, so set about creating character maps for A-Z and 0-9 to display, based on a standard 7 segment display, and was pretty impressed with the result. (You'll have to excuse the overexposed image, it looks better in real life.)

One of the original test patterns I set up

"HEL" of the standard "HELLO WORLD" test output phrase I also do a lot of theatre lighting in my area and at a technical meeting for the next production it was discussed that it would fit the scene/song

well if they utilised their existing projector to show a stock exchange style ticker. Knowing that I was already on the conceptual route to this, I volunteered to make a large scale version for the production. It is constructed from free hardboard from the IKEA recycling area (the front panel is actually half of the back of a wardrobe, it had zero damage, so not really sure why it had been discarded) which was then stapled onto a 2"x1" batten frame around the edges. As the final product is 42x7 (294) pixels, the most boring part was drilling the 294 holes required to mount them! So I plodded through doing a few columns every night for a few nights and was finished soon enough!

SketchUp model of the rear of the finished product

Front view of SketchUp model

Schematic of final electrical configuration Due to the way I incrementally built up the code, bolting functions on as it developed, I started to encounter major memory issues along the way, and had to trim a lot of non-essential parts of code out and radically change other functions in order for it to run correctly. This included removing lower case character maps (not used for the product in this setup) and changing the pixel layout from being stored in a 42x7 INT array into a mathematical equation which returned a pixel ID for any given x, y coordinate. I decided to stick with the memory constraints of the UNO as it improved my programming skills by analysing the memory usage and seeing where savings could be made, although as time became incredibly tight (it wasn't working in time for our first production, unfortunately) I did consider 'cheating' and buying a MEGA just to get it working, but I'm glad I stuck with it.

SCHEMATICS

CODE #include #include #ifdef __AVR__ #include #endif #define stripPin 6 #define stripPinB 9 #define ledTotal 150 // zero indexed, so one less than you need. I.e. 50 leds = 49 here #define ledTotalB 144 // zero indexed... #define rowSize 6 // zero indexed... #define columnSize 41 // zero indexed... #define charWidth 5 // ** one indexed ** byte displayOutput[columnSize + 1] = {0}; byte displayColors[columnSize + 1] = {0}; byte currentStatus = 0; // 0 = off, 1 = on unsigned int maxLoad = 0; // was 68 with lower case chars, 42 without -- 40 without l/r arrow -- 42 WITH PLUS AND DOT byte displayLetters[42][charWidth] = { // [A] = chars/digits contained in array, [B] = charWidth (no need to add 1, as was 'one indexed' at #define) {0x3e, 0x51, 0x49, 0x45, 0x3e}, // 0 // , 0x00 {0x00, 0x42, 0x7f, 0x40, 0x00}, // 1 {0x42, 0x61, 0x51, 0x49, 0x46}, // 2 {0x21, 0x41, 0x45, 0x4b, 0x31}, // 3 {0x18, 0x14, 0x12, 0x7f, 0x10}, // 4 {0x27, 0x45, 0x45, 0x45, 0x39}, // 5 {0x3c, 0x4a, 0x49, 0x49, 0x30}, // 6 {0x01, 0x71, 0x09, 0x05, 0x03}, // 7 {0x36, 0x49, 0x49, 0x49, 0x36}, // 8 {0x06, 0x49, 0x49, 0x29, 0x1e}, // 9 {0x7e, 0x11, 0x11, 0x11, 0x7e}, // A {0x7f, 0x49, 0x49, 0x49, 0x36}, // B {0x3e, 0x41, 0x41, 0x41, 0x22}, // C {0x7f, 0x41, 0x41, 0x22, 0x1c}, // D

{0x7f, 0x49, 0x49, 0x49, 0x41}, // E {0x7f, 0x09, 0x09, 0x09, 0x01}, // F {0x3e, 0x41, 0x49, 0x49, 0x7a}, // G {0x7f, 0x08, 0x08, 0x08, 0x7f}, // H {0x00, 0x41, 0x7f, 0x41, 0x00}, // I {0x20, 0x40, 0x41, 0x3f, 0x01}, // J {0x7f, 0x08, 0x14, 0x22, 0x41}, // K {0x7f, 0x40, 0x40, 0x40, 0x40}, // L {0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M {0x7f, 0x04, 0x08, 0x10, 0x7f}, // N {0x3e, 0x41, 0x41, 0x41, 0x3e}, // O {0x7f, 0x09, 0x09, 0x09, 0x06}, // P {0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q {0x7f, 0x09, 0x19, 0x29, 0x46}, // R {0x46, 0x49, 0x49, 0x49, 0x31}, // S {0x01, 0x01, 0x7f, 0x01, 0x01}, // T {0x3f, 0x40, 0x40, 0x40, 0x3f}, // U {0x1f, 0x20, 0x40, 0x20, 0x1f}, // V {0x3f, 0x40, 0x38, 0x40, 0x3f}, // W {0x63, 0x14, 0x08, 0x14, 0x63}, // X {0x07, 0x08, 0x70, 0x08, 0x07}, // Y {0x61, 0x51, 0x49, 0x45, 0x43}, // Z {0x00, 0x00, 0x00, 0x00, 0x00}, // space {0x10, 0x18, 0x1c, 0x18, 0x10}, // new up arrow {0x04, 0x0c, 0x1c, 0x0c, 0x04}, // new down arrow {0x08, 0x08, 0x08, 0x08, 0x08}, // dash / maintain {0x08, 0x08, 0x3E, 0x08, 0x08}, // plus {0x00, 0x60, 0x60, 0x00, 0x00} // full stop }; const int stockQty = 17; // this is the amount of different stock values to be contained, *!* ONE indexed *!* const int stockStepQty = 5; // *!* ONE indexed *!* int stockStep = 0; /*String stockNames[stockQty] = { "MH", "EJ", "SG", "MC", "AS", "JWL", "RP", "HCJ", "JT", "KC", "HCN", "MK", "JWK", "RB", "KS", "EC", "AW" };*/ /*int stockValues[stockStepQty][stockQty] = { // dies 3 from end, color wise {5, 12, 41, 52, 157, 74, 63, 96, 17, 86, 104, 49, 76, 46, 91, 61, 121}, {6, 13, 40, 52, 155, 73, 60, 98, 18, 85, 105, 48, 77, 47, 90, 59, 125}, {6, 12, 39, 53, 155, 75, 58, 99, 18, 84, 104, 46, 78, 46, 88, 60, 123}, {7, 11, 42, 55, 156, 74, 59, 98, 17, 85, 106, 47, 77, 45, 92, 58, 124}, {6, 13, 40, 54, 157, 75, 60, 97, 18, 85, 105, 48, 77, 46, 95, 60, 122} };*/

Adafruit_NeoPixel strip = Adafruit_NeoPixel(ledTotal + 1, stripPin, NEO_RGB + NEO_KHZ800); Adafruit_NeoPixel stripB = Adafruit_NeoPixel(ledTotalB + 1, stripPinB, NEO_RGB + NEO_KHZ800); void setup() { strip.begin(); strip.show(); stripB.begin(); stripB.show();

pinMode(13, OUTPUT); } String inputString = "MJC|-5 CDL|-1 HJC^+10 MAK^+2 GJK|-8 EBJ^+5 HJC^+10 JCW^+0.02 ADS|-3 SEG^+5 RFB^+7 KGO^+2 MJH|-0.043 KHS^+0.054 SIC^0.008 EJC^+0.001 AMW^+5 LDK|-7 JCT^+9 JKM^+4 RJP|-4 SKC^+9 JLW|-5 HKC^+5 LMP^+7 ANS^+5 "; String colString = "00011100001110000222200002220000111000022200002222000022222200001110000222000022200002 void loop() { for (int i = 0; i < inputString.length(); i++) { char currentChar = inputString[i]; int currentCol, colorMode;// = int(colString[i]) - 48; // minus 48 because int("0") will return the ascii value of char '0' (48) if ((currentChar >= 'A') && (currentChar = '0') && (currentChar = '0') && (currentChar = 'A') && (currentChar = 'a') && (currentChar = 120) z++; return z; } void setMappedColor(int columnID, int rowID, long pixelColor) { int mappedPixel = getMappedPixel(columnID, rowID); if (mappedPixel < ledTotal) { strip.setPixelColor(mappedPixel, pixelColor); } else { mappedPixel = mappedPixel - ledTotal; stripB.setPixelColor(mappedPixel, pixelColor); } } void colorAll(long color) { for (int i = 0; i =1) {digitalWrite(LED5, HIGH); myline-=1;} else {digitalWrite(LED5, LOW);} } void displayChar(char c){ if (c == 'a'){for (int i = 0; i ")){ ser.print(getStr); lcd.setCursor(14, 3); lcd.print("Wifion"); } else{ ser.println("AT+CIPCLOSE"); // alert user Serial.println("AT+CIPCLOSE"); lcd.setCursor(13, 3); lcd.print("Wifioff"); } } } //co2 measurement sensor-------------------------------------------------------float MGRead(int mg_pin) { int i; float v=0; for (i=0;i=ZERO_POINT_VOLTAGE) { return -1; } else { return pow(10, ((volts/DC_GAIN)-pcurve[1])/pcurve[2]+pcurve[0]); } } //--------------------------------------------

139) A Fun and Easy Arduino Game Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

Adafruit NeoPixel LED Strip Starter Pack - 30 LED meter SparkFun Piezo element

×

1

×

4

×

4

Resistor 220 ohm

SparkFun Resistor 1M ohm

×

4

×

4

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT Bongo Hero was created for the "Fête de la science," an annual event in France to promote science and technology. I am currently a software developer at Orange labs in Caen, and for this event we opened our labs to the public and built demonstrations, Bongo Hero was one of them. The goal of this demonstration was to show how we could build things easily thanks to Arduino. This tutorial shows how to build Bongo Hero using four LED strips of one meter each (30 LEDs per strip), but the code is easily configurable, so you can build your own version with the number of strips you want, the number of LEDs you want, and even adapt the difficulty of the game. Test the LED strips To test the LED strips and the FastLed library that is used, there is a very nice tutorial showing the possibilities offered by the library. I followed it to get started with the strips and the library. The four strip must be connected to digital pin 2, 3, 4 and 5 as you can see in the setup function: FastLED.addLeds(leds[0], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); FastLED.addLeds(leds[1], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); FastLED.addLeds(leds[2], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);

FastLED.addLeds(leds[3], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); Test the piezo elements The Arduino official example for using a piezo element is very well explained. The four piezo elements must be connected to analog pins A0, A1, A2, A3. To sum up: Led strip digital pin | Piezo element analog pin -------------------------------------2

| A0

3

| A1

4

| A2

5

| A3

Configure the game At the beginning of the source file, you'll find preprocessor directives that will enable you to adapt the difficulty and the gameplay of the game. Here are the most useful: #define MIN_INTERVAL 5 // the minimum number of leds switched off between two tiles #define LEVEL_DURATION 5 // number of successful tap before level up #define MIN_TILE_DELAY 50 // in milliseconds, minimum duration for a tile in a position #define MAX_TILES_PER_STRIP 3 // the maximum number of tiles present at the same time on a led strip #define TILE_GENERATION_PROB 15 // probability to generate a new

tile when possible the smaller it is, the more likely it is to generate one #define LEVEL_SPEED_INCREASE 5 // in milliseconds, increase the speed of the led strip refresh rate when level

SCHEMATICS

CODE #include #define LED_TYPE WS2811 #define NUM_STRIPS 4 // number of led strips, when changing this value, the setup function must be updated #define BRIGHTNESS 64 // brightness of the leds #define TILE_LENGTH 4 // number of leds per tile #define COLOR_ORDER GRB #define MIN_INTERVAL 5 // the minimum number of leds switched off between two tiles #define LEVEL_DURATION 5 // number of successful tap before level up #define MIN_TILE_DELAY 50 // in milliseconds, minimum duration for a tile in a position #define PIEZO_THRESHOLD 500 #define GAME_OVER_DELAY 1000 // in miliseconds, duration of the break when game is over #define INIT_REFRESH_RATE 250 // in milliseconds, led strips refresh rate when game starts #define NUM_LEDS_PER_STRIP 30 // number of leds per strip #define MAX_TILES_PER_STRIP 3 // the maximum number of tiles present at the same time on a led strip #define TILE_GENERATION_PROB 15 // probability to generate a new tile when possible the smaller it is, the more likely it is to generate one #define LEVEL_SPEED_INCREASE 5 // in milliseconds, increase the speed of the led strip refresh rate when level int score; int currentDelay; CRGB currentColor; unsigned long lastTime; int numTiles[NUM_STRIPS];

bool canCheck[NUM_STRIPS]; bool canCreate[NUM_STRIPS]; int currentIndex[NUM_STRIPS]; int tiles[NUM_STRIPS][MAX_TILES_PER_STRIP]; CRGB leds[NUM_STRIPS][NUM_LEDS_PER_STRIP]; void setup() { delay(3000); // power-up safety delay FastLED.addLeds(leds[0], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); FastLED.addLeds(leds[1], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); FastLED.addLeds(leds[2], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); FastLED.addLeds(leds[3], NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); InitGame(); randomSeed(37); Serial.begin(9600); FastLED.setBrightness(BRIGHTNESS); } void loop() { for(int i = 0; i < NUM_STRIPS; i++) { int piezoValue = analogRead(i); // check if a bongo was hit if(piezoValue > PIEZO_THRESHOLD) { bool ok = false; for(int j = 0; j < MAX_TILES_PER_STRIP; j++) { if(tiles[i][j] < TILE_LENGTH*2 && tiles[i][j] != -1 && canCheck[i]) { score++; ok = true; canCheck[i] = false; FastLED.setBrightness(3*BRIGHTNESS); break; } } if(!ok && canCheck[i]) { GameOver(); }

} } unsigned long currentTime = millis(); if(currentTime - lastTime > currentDelay) { lastTime = currentTime; // level up if(score % LEVEL_DURATION == 0 && score > 0) { currentDelay -= LEVEL_SPEED_INCREASE; if(currentDelay < MIN_TILE_DELAY) currentDelay = MIN_TILE_DELAY; // maximum speed currentColor = nextColor(); } // one tile maximum will be created during each refresh bool tileCreated = false; // refresh display for(int i = 0; i < NUM_STRIPS; i++) { SwitchOffLEDs(leds[i]); // Fill last tile FillTile(TILE_LENGTH - 1, leds[i], CRGB::White); if(numTiles[i] < MAX_TILES_PER_STRIP) { // if there is enough space left on the strip // we try to create a new tile // 1/6 chance to create a new tile if(canCreate[i] && random(0, TILE_GENERATION_PROB) == 0 && !tileCreated) { numTiles[i]++; tiles[i][currentIndex[i]] = NUM_LEDS_PER_STRIP - 1; currentIndex[i]++; tileCreated = true; } canCreate[i] = true; } // if tiles array is full, // next tile will be created at index 0 if( currentIndex[i] == MAX_TILES_PER_STRIP ) { currentIndex[i] = 0; } // Fill tiles on the strip

for(int j = 0; j < MAX_TILES_PER_STRIP; j++) { if(tiles[i][j] == -1) continue; if(!canCheck[i] && tiles[i][j] < TILE_LENGTH + MIN_INTERVAL && MIN_INTERVAL >= TILE_LENGTH) { // We don't show a tile if it has already been taken in account by the player. // This cannot be done this way if MIN_INTERVAL < TILE_LENGTH, // in this case we'll have a fallback behaviour (we'll see the tile leaving the strip). } else { FillTile(tiles[i][j], leds[i], currentColor); } tiles[i][j]--; // if tile exits the strip we decrement the number of tiles if(tiles[i][j] == 0){ numTiles[i]--; tiles[i][j] = -1; if(score > 0) { if(canCheck[i]) { GameOver(); } canCheck[i] = true; } } // check if the tile is at the beginning of the strip if(tiles[i][j] >= NUM_LEDS_PER_STRIP - TILE_LENGTH - MIN_INTERVAL) canCreate[i] = false; } } FastLED.show(); FastLED.setBrightness(BRIGHTNESS); } } void FillTile(int tile, CRGB leds[], CRGB color) { for(int i = tile; i > tile - TILE_LENGTH; i--) { leds[i] = color; if (i == 0) break; } } void SwitchOffLEDs(CRGB leds[]) {

for(int i = 0; i < NUM_LEDS_PER_STRIP; i++) { leds[i] = CRGB::Black; } } void InitGame() { score = 0; lastTime = millis(); currentColor = CRGB::Yellow; currentDelay = INIT_REFRESH_RATE; for(int i = 0; i < NUM_STRIPS; i++) { numTiles[i] = 0; canCheck[i] = true; canCreate[i] = true; currentIndex[i] = 0; for(int j = 0; j < MAX_TILES_PER_STRIP; j++) { tiles[i][j] = -1; } } } void GameOver() { for(int i = 0; i < NUM_STRIPS; i++) { // Fill last tile in red FillTile(TILE_LENGTH - 1, leds[i], CRGB::Red); } FastLED.show(); delay(GAME_OVER_DELAY); InitGame(); } CRGB nextColor() { switch (score) { case LEVEL_DURATION: return CRGB::Blue; case 2*LEVEL_DURATION: return CRGB::Green; case 3*LEVEL_DURATION: return CRGB::Purple; case 4*LEVEL_DURATION: return CRGB::Orange; case 5*LEVEL_DURATION:

return CRGB::Pink; case 6*LEVEL_DURATION: return CRGB::Salmon; case 7*LEVEL_DURATION: return CRGB::DeepSkyBlue; case 8*LEVEL_DURATION: return CRGB::ForestGreen; default: return CRGB::Yellow; } }

140) Clock with Arduino Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

Adafruit display nokia 5110

×

1

×

1

×

1

Jumper wires (generic)

Resistor 221 ohm ×

1

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT Arduino clock, easy to set up, you can set the date and time by the Serial monitor, this projects uses few components only jumpers, Arduino, and display Nokia 5110/3110, and ready // pin 3 - Serial clock out (SCLK) // pin 4 - Serial date out (DIN) // pin 5 - date/Command select (D/C) // pin 6 - LCD chip select (CS/CE) // pin 7 - LCD reset (RST)

SCHEMATICS

CODE #include #include // pin 3 - Serial clock out (SCLK) // pin 4 - Serial date out (DIN) // pin 5 - date/Command select (D/C) // pin 6 - LCD chip select (CS/CE) // pin 7 - LCD reset (RST)

Adafruit_PCD8544 display = Adafruit_PCD8544(3,4,5,6,7); int second,minute, hour, day, mounth,year; unsigned long UtlTime; void setup() pinMode(2,OUTPUT); UtlTime=0; { minute=0; hour=0; day=0; mounth=0; year=0; Serial.begin(9600); display.begin(); display.setContrast(50); // Adjust the display contrast display.clearDisplay(); //Apaga o buffer e o display display.setTextSize(1); //Seta o tamanho do texto display.setTextColor(BLACK); //Seta a cor do texto

display.print(" date e hour "); display.setCursor(0,10); display.print(" com Arduino"); display.display(); delay (5000);

//Configura o minute display.clearDisplay(); display.setCursor(0,0); display.print("minute: ");

display.display(); Serial.print("\nin between minute:"); while(minute==0) { if (Serial.available() > 0) { minute= Serial.parseInt(); } } display.print(minute); display.display(); delay(1000); //Configura a hour display.clearDisplay(); display.setCursor(0,0); display.print("hour: "); display.display(); Serial.print("\nin between hour:"); while(hour==0) { if (Serial.available() > 0) { hour= Serial.parseInt(); } } display.print(hour); display.display(); delay(1000); //Configura o day display.clearDisplay(); display.setCursor(0,0); display.print("day: "); display.display();

Serial.print("\nin between day:"); while(day==0) { if (Serial.available() > 0) { day= Serial.parseInt(); } } display.print(day); display.display(); delay(1000); //Configura o mês display.clearDisplay(); display.setCursor(0,0); display.print("mounth: "); display.display(); Serial.print("\nin between mounth:"); while(mounth==0) { if (Serial.available() > 0) { mounth= Serial.parseInt(); } } display.print(mounth); display.display(); delay(1000); //Configura o year display.clearDisplay(); display.setCursor(0,0); display.print("year: "); display.display();

Serial.print("\nin between year:"); while(year==0) { if (Serial.available() > 0) { year= Serial.parseInt(); } } display.print(year); display.display(); delay(1000); display.clearDisplay(); } void loop() { if(millis()-UtlTime59) { second=0; minute++; UtlTime=millis(); if(minute>59) {

hour++; minute=0; if(hour>23) { day++; hour=0; if(mounth==1||mounth==3||mounth==5||mounth==7||mounth==8||mounth==10||mounth { if(day>31) { day=1; mounth++; if(mounth>12) { year++; mounth=1; } } } else if(mounth==2) { if(year%400==0) { if(day>29) { day=1; mounth++; } } else if((year%4==0)&&(year%100!=0)) { if(day>29) { day=1;

mounth++; } } else { if(day>28) { day=1; mounth++; } } } else { if(day>30) { day=1; mounth++; } } } } } display.clearDisplay(); delay(1000); Serial.print(day); Serial.print("/"); Serial.print(mounth); Serial.print("/"); Serial.print(year); Serial.println(); display.setCursor(0,0);

display.print("date "); display.print(day); display.print("/"); display.print(mounth); display.print("/"); display.print(year);

display.display(); Serial.print(hour); Serial.print(":"); Serial.print(minute); Serial.print(":"); Serial.print(second); Serial.print("\n"); Serial.println(); display.setCursor(0,10); display.print("hour "); display.print(hour); display.print(":"); display.print(minute); display.print(":"); display.print(second); display.display(); char tecla; tecla = Serial.read(); if(tecla=='1'){ digitalWrite(2,LOW); } if(tecla=='2'){ digitalWrite(2, HIGH); }

}

141) Arduino Proximity Alarm Distance Meter Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

Ultrasonic Sensor - HC-SR04 (Generic)

×

1

×

1

×

1

passive buzzer module U can find it on ali express, it costs less than a dollar.

HC-06 Bluetooth Module

×

1

×

1

×

1

LED (generic)

Male/Female Jumper Wires

APPS AND ONLINE SERVICES Arduino IDE

arduino bluetooth controller apk U can find it on playstore microsoft visio professional

ABOUT THIS PROJECT As earlier stated, this project can perform a number of tasks like proximity alarm ranging from 2cm to 400cm (i.e minimum and max range of the ultrasonic sensor) depending on the distance you input in your Arduino sketch. It can also be used for electronic measurement of distances ranging from 2cm to 400cm(4m). You can also see the distance reading in meters, cm, and inches in your serial monitor. The reason for the Bluetooth module is to see your serial readings mobile via Bluetooth through the Android application I mentioned earlier Arduino Bluetooth controller. Launch the Android application:

Before connecting

Select terminal mode

Distance reading starts immediately after successful connection.

SCHEMATICS

CODE

const int buzzerPin = 8; const int trigPin = 11;

// buzzzer signal pin attached to digital pin 8 // ultrasonic triggerPin connected to digital pin 11

const int echoPin = 10; // ultrasonic echoPin connected to digital pin 10 int ledPin = 13; // LED positive connecteed to digital pin 13 (no need for resistor) long duration; float distanceMeters, distanceCm, distanceInch; void setup() { // define all digital and analog pins pinMode(13, OUTPUT); // LED pin as output pinMode(trigPin, OUTPUT); // trigger pin as output because it sends signal pinMode(8, OUTPUT); // buzzer pin as output pinMode(echoPin, INPUT); // echo pin as input becaue it recievs signals Serial.begin(9600); // initiate serial communication } void loop() { digitalWrite(trigPin, HIGH); receiving delayMicroseconds(10); digitalWrite(trigPin, LOW);

// initiate the ultrasonic sensor for sending and

duration = pulseIn(echoPin, HIGH); distanceMeters = duration * 0.00034 / 2; // speed of sound per second; divide by 2 due to then sound coming back to the echo part of the sensor distanceCm = duration * 0.034 / 2; distanceInch = duration * 0.0133 / 2; Serial.print("Distance: "); Serial.print(distanceMeters); Serial.println(" Meters"); delay(300);

// print distance (meters) in serial monitor

Serial.print("Distance: "); Serial.print(distanceCm); Serial.println(" cm"); delay(300);

// print distance (centi meters) in serial monitor

Serial.print("Distance: "); // print distance (inches) in serial monitor Serial.print(distanceInch); Serial.println(" inch"); delay(300); Serial.println("----------------------------"); // seoeration

if (distanceCm 100 ) digitalWrite(13, LOW); noTone(buzzerPin); } }

// ...... with delay as interval // u can tweak the code to suit yourn needs

{

142) Arduino Music Player Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

Generic 16x2 LCD Generic IR Receiver Resistor 221 ohm

×

1

×

1

×

1

×

2

×

1

×

1

×

1

×

23

×

1

Buzzer

General Purpose Transistor NPN S8050

Rotary potentiometer (generic)

Jumper wires (generic)

Solderless Breadboard Full Size

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT As you've already seen, I've built a noob-ish music player (currently loaded with only 2 short songs), that is controlled via a Remote Controller. The project, as a circuit is complete, but I'm still trying to figure out how to make the code even better and tweek it a little bit. I'll explain that later.

The only puprose for me making this simple project, is to make myself better at using the Arduino board and code and to say that I've made something that I find a little cool :) Breaking The Code The libraries I've included: #include #include Pin Initialization LiquidCrystal lcd(12, 11, 5, 4, 3, 2); int speakerPin = 9; int RECV_PIN = 13; Defining different notes

#define cL 129 #define cLS 139 #define dL 146 #define dLS 156 #define eL 163 #define fL 173 #define fLS 185 #define gL 194 #define gLS 207 #define aL 219 #define aLS 228 #define bL 232 #define c 261 #define cS 277 #define d 294 #define dS 311 #define e 329 #define f 349 #define fS 370 #define g 391 #define gS 415 #define a 440 #define aS 455 #define b 466 #define cH 523 #define cHS 554 #define dH 587

#define dHS 622 #define eH 659 #define fH 698 #define fHS 740 #define gH 784 #define gHS 830 #define aH 880 #define aHS 910 #define bH 933 Buzzer Code void beep (int speakerPin, int freqHz, long timeMs) { double timeDelay = (double)(1000000/freqHz); double timeLoop = (double)((timeMs*1000)/(timeDelay*2)); for(int i = 0; i < timeLoop; i++) { digitalWrite(speakerPin, HIGH); delayMicroseconds(timeDelay); digitalWrite(speakerPin, LOW); delayMicroseconds(timeDelay); } delay(20); } Songs void Smoke() { beep(speakerPin, cH, 500);

beep(speakerPin, dHS, 500); beep(speakerPin, fH, 500); delay(250); beep(speakerPin, cH, 500); beep(speakerPin, dHS, 500); beep(speakerPin, fHS, 250); beep(speakerPin, fH, 550); delay(350); beep(speakerPin, cH, 500); beep(speakerPin, dHS, 500); beep(speakerPin, fH, 500); delay(250); beep(speakerPin, dHS, 500); beep(speakerPin, cH, 1500); delay(250); } void Jingle() { beep(speakerPin, e, 300); beep(speakerPin, e, 300); beep(speakerPin, e, 500); delay(250); beep(speakerPin, e, 300); beep(speakerPin, e, 300); beep(speakerPin, e, 500); delay(350);

beep(speakerPin, e, 350); beep(speakerPin, g, 350); beep(speakerPin, c, 350); beep(speakerPin, d, 350); beep(speakerPin, e, 1000); delay(250); beep(speakerPin, f, 350); beep(speakerPin, f, 350); beep(speakerPin, f, 350); beep(speakerPin, f, 300); beep(speakerPin, f, 300); beep(speakerPin, e, 320); beep(speakerPin, e, 320); beep(speakerPin, e, 150); beep(speakerPin, e, 150); beep(speakerPin, e, 150); beep(speakerPin, d, 340); beep(speakerPin, d, 340); beep(speakerPin, e, 440); beep(speakerPin, d, 540); beep(speakerPin, g, 440); delay(2000); } Printing the loading message void setup() { lcd.begin(16,2);

irrecv.enableIRIn(); pinMode(speakerPin,OUTPUT); lcd.print("Mike Player"); lcd.setCursor(0,1); lcd.print("Loading."); delay(1000); lcd.print("."); delay(1000); lcd.print("."); delay(1000); lcd.print("."); delay(1000); lcd.print("."); delay(1000); lcd.clear(); lcd.print("Press Play"); } And the short menu I've made (needs improvement) void loop() { if (irrecv.decode(&results)) { lcd.clear(); lcd.print("Select Song"); lcd.setCursor(0,1); lcd.print("+:Song List"); if (results.value==0xA3C8EDDB) //+

{ lcd.clear(); lcd.setCursor(0,0); lcd.print("Smoke On The Water: 1 Jingle Bells: 2"); for (int positionCounter = 0; positionCounter < 64; positionCounter++) { lcd.scrollDisplayLeft(); delay(300); } } if (results.value == 0x9716BE3F) //1 { Smoke(); } if (results.value == 0x3D9AE3F7) //2 { Jingle(); } irrecv.resume(); } } SCHEMATICS

CODE #include #include LiquidCrystal lcd(12, 11, 5, 4, 3, 2); int speakerPin = 9; int RECV_PIN = 13; #define cL 129 #define cLS 139 #define dL 146 #define dLS 156 #define eL 163 #define fL 173 #define fLS 185 #define gL 194 #define gLS 207 #define aL 219 #define aLS 228 #define bL 232 #define c 261 #define cS 277 #define d 294 #define dS 311 #define e 329 #define f 349 #define fS 370 #define g 391

#define gS 415 #define a 440 #define aS 455 #define b 466 #define cH 523 #define cHS 554 #define dH 587 #define dHS 622 #define eH 659 #define fH 698 #define fHS 740 #define gH 784 #define gHS 830 #define aH 880 #define aHS 910 #define bH 933 IRrecv irrecv(RECV_PIN); decode_results results;

void beep (int speakerPin, int freqHz, long timeMs) { double timeDelay = (double)(1000000/freqHz); double timeLoop = (double)((timeMs*1000)/(timeDelay*2)); for(int i = 0; i < timeLoop; i++) { digitalWrite(speakerPin, HIGH); delayMicroseconds(timeDelay); digitalWrite(speakerPin, LOW); delayMicroseconds(timeDelay); } delay(20); }

void Smoke() { beep(speakerPin, cH, 500); beep(speakerPin, dHS, 500); beep(speakerPin, fH, 500);

delay(250); beep(speakerPin, cH, 500); beep(speakerPin, dHS, 500); beep(speakerPin, fHS, 250); beep(speakerPin, fH, 550); delay(350); beep(speakerPin, cH, 500); beep(speakerPin, dHS, 500); beep(speakerPin, fH, 500); delay(250); beep(speakerPin, dHS, 500); beep(speakerPin, cH, 1500); delay(250); }

void Jingle() { beep(speakerPin, e, 300); beep(speakerPin, e, 300); beep(speakerPin, e, 500); delay(250); beep(speakerPin, e, 300); beep(speakerPin, e, 300); beep(speakerPin, e, 500); delay(350); beep(speakerPin, e, 350); beep(speakerPin, g, 350); beep(speakerPin, c, 350); beep(speakerPin, d, 350); beep(speakerPin, e, 1000); delay(250); beep(speakerPin, f, 350); beep(speakerPin, f, 350);

beep(speakerPin, f, 350); beep(speakerPin, f, 300); beep(speakerPin, f, 300); beep(speakerPin, e, 320); beep(speakerPin, e, 320);

beep(speakerPin, e, 150); beep(speakerPin, e, 150); beep(speakerPin, e, 150); beep(speakerPin, d, 340); beep(speakerPin, d, 340); beep(speakerPin, e, 440); beep(speakerPin, d, 540); beep(speakerPin, g, 440); delay(2000); }

void setup() { lcd.begin(16,2); irrecv.enableIRIn(); pinMode(speakerPin,OUTPUT); lcd.print("Mike Player"); lcd.setCursor(0,1); lcd.print("Loading."); delay(1000); lcd.print("."); delay(1000); lcd.print("."); delay(1000); lcd.print("."); delay(1000); lcd.print("."); delay(1000); lcd.clear(); lcd.print("Press Play"); } void loop() { if (irrecv.decode(&results)) { lcd.clear();

lcd.print("Select Song"); lcd.setCursor(0,1); lcd.print("+:Song List"); if (results.value==0xA3C8EDDB) //+ { lcd.clear(); lcd.setCursor(0,0); lcd.print("Smoke On The Water: 1 Jingle Bells: 2"); for (int positionCounter = 0; positionCounter < 64; positionCounter++) { lcd.scrollDisplayLeft(); delay(300); }

} if (results.value == 0x9716BE3F) //1 { Smoke(); } if (results.value == 0x3D9AE3F7) //2 { Jingle(); } irrecv.resume(); } }

143) Proximity Lamp using Arduino Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

10 mega ohm resistor

×

1

×

1

×

1

LED (generic)

Aluminium foil Paper

×

1

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT In this project I will show you how you can create a proximity sensor using aluminium foil and a high value resistor (resistance from 10 MΩ to 40 MΩ). It works based on the Arduino capacitive sensing Library. Whenever you bring your hand (any conductive object) near to the sensor, the LED's brightness changes depending on the distance. At minimum distance, it shows maximum brightness. The capacitive sensor library turns two or more Arduino pins into capacitive sensor, which can sense the electrical capacitance of the human body. All the sensor setup requires is a medium to high value resistor and a small (to large) piece of aluminium foil on the end. At its most sensitive, the sensor will start to sense a hand or body inches away from the sensor. How do capacitive sensors work? Capacitive sensing is a proximity sensing technology. Capacitive sensors work by generating an electric field, and detecting near by objects by sensing whether this field has been disrupted. Capacitive sensors can detect anything that is conductive or that has a significantly different permittivity than air, like a human body or hand.Permittivity is the measure of how difficult it is to create an electric field around a material. It’s the ability of a substance to store electrical energy in an electric field. Materials To begin you will need:

· Arduino Uno · USB cable · 10 MΩ resistor · LED · Aluminium foil (size 4 cmX4cm) Sensor Design Small sensors (about the size of a finger print) work best as touch sensitive buttons, while larger sensors work better in proximity mode. The size of the aluminium foil can impact the sensitivity of the sensor, so try a few different sizes if you want and see how this changes the way that the sensor reacts. Circuit Diagram

Circuit Diagram Hardware Setup Insert a 10 M ohm resistor in between 2nd and 4th pin of Arduino. As per the program pin 4 is receive pin.Connect aluminium foil to the receive pin. Connect Led’s +ve terminal to 9th pin –ve terminal to GND of Arduino. Code: #include CapacitiveSensor cs_2_4 = CapacitiveSensor(2,4); // 10M ohm resistor between pins 2 & 4, pin 4 is sensor pin, add a wire and or foil int in = 2; int out = 4; void setup() { Serial.begin(9600); // // initialize serial communication at 9600 bits per second: pinMode(4, INPUT); pinMode(9, OUTPUT); } void loop() { long start = millis(); long total1 = cs_2_4.capacitiveSensor(30); //sensor resoultion. Default 30. // increase for higher resolution, but slower performance. Serial.print(millis() - start); Serial.print("\t"); Serial.println(total1);

// check on performance in milliseconds //tab character for debug window spacing // print sensor output 1

delay(10); if(total1>=140)

// arbitrary delay to limit data to serial port // change this based on serial Monitor's output

{ analogWrite(9, total1); } else { digitalWrite(9,LOW); } } Setting up the Arduino Great! Now all of the physical work is done and we’re off to the code. Make sure that you’ve installed capacitive sensing library. Now we are ready to test your sensor! Make sure that your computer is plugged into the wall, or the Arduino is connected to ground as this improves the stability of the sensor. To check the output of the sensor, open the Serial monitor in the Arduino programming environment (make sure the monitor is set to 9600 baud as that is what is specified in the code). If it is working correctly, moving your hand closer and farther from the foil should change the brightness of led. The sensor plate and your body forms a capacitor. We know that a capacitor stores charge. The more its capacitance, the more charge it can store. The capacitance of this capacitive touch sensor depends on how close your hand is to the plate. What does the Arduino do? Basically the Arduino measures how much time the capacitor (i.e. the touch sensor) takes to charge, giving it an estimate of the capacitance. The

capacitance may be very small, nevertheless the Arduino measures it with accuracy SCHEMATICS

CODE #include CapacitiveSensor cs_2_4 = CapacitiveSensor(2,4); // 10M ohm resistor between pins 2 & 4, pin 4 is sensor pin, add a wire and or foil int in = 2;

int out = 4;

void setup() { Serial.begin(9600); // // initialize serial communication at 9600 bits per second: pinMode(4, INPUT); pinMode(9, OUTPUT); } void loop() { long start = millis(); long total1 = cs_2_4.capacitiveSensor(30); //sensor resoultion. Default 30. // increase for higher resolution, but slower performance. Serial.print(millis() - start); // check on performance in milliseconds Serial.print("\t"); //tab character for debug window spacing Serial.println(total1); // print sensor output 1 delay(10); // arbitrary delay to limit data to serial port

if(total1>=140) // change this based on serial Monitor's output { analogWrite(9, total1); } else { digitalWrite(9,LOW); } }

144) Arduino 3D Bar Charts Projet

COMPONENTS AND SUPPLIES Arduino Mega 2560 & Genuino Mega 2560

Elegoo 2.8 inch TFT LCD Shield Rotary potentiometer (generic)

×

1

×

1

×

2

×

1

Solderless Breadboard Half Size

Male/Male Jumper Wires

×

1

ABOUT THIS PROJECT We all use sensors in our projects, collecting data from them and performing tasks with the data, but would it not be nice if we could have a visual representation of this data live? LCD graphing has been around for some time but the problem is that it is difficult and time consuming to program from scratch. This project aims to make graphing easy and accessible to everyone. A template is provided on which the client can build, and in minutes, you can graph any sensor data live on a beautiful graph. Photo

The device Functionality This project builds on the Bar Chart tutorial found here, bringing the third dimension into play. The client has to only edit 2 variables and their graph is ready, the graph's colours can also be personalised with ease, below are some photos with some of the styles you can have the graph in.

Black and White

Pink and Purple

Powerful Blue The graph will plot the data live as the device reads it, in this example, two potentiometers are used, the device reads their values and then plots them on the graph. Here is a diagram showing the functionality overview.

Functionality Overview Below is a diagram with the project's code overview.

Code Overview Read Sensors will read the sensors the user attached to the device, the values can be set constant. ProcessData will map the sensor data to the graph GraphData will draw the graph and graph the data on the LCD. Drawing the Graph As the graph is 3 dimensional there are more steps involved in drawing it, the images below guide you through all the steps taken to draw the graph.

Who the device boots up, it will draw the outline of the graph, label it and map the values on the y axis

It will then read the sensor data and then draw 2 dimensional bars for the values

The device will then draw the outline of the 3D graph with lines A Lecture All you have to know to be able to proceed with this project is a broad understanding onto how things are positioned on the TFT LCD, this is explained below. I refer to the whole LCD as the canvas, this is where everything is drawn, all TFT LCD libraries work quite similarly, so the functions in this code should also work with other libraries. Below is a sketch of a quadrilateral (a rectangle) being drawn on a TFT LCD.

Sketch of Shape In this sketch, a rectangle is drawn, each point is labelled, the line of code that is used to draw a rectangle is this, tft.fillRect(originX, originY, sizeX, sizeY, Colour); originX is represented by 'z' on the diagram above, this is the distance from the right of the screen to the shape. originY is represented by 'x' on the sketch, this is the distance form the top of the screen to the shape. sizeX is the size of the shape on the x axis, this is the length of the shape. sizeY is the size of the shape on the y axis, this is the height of the shape. Benefits Theuseroperatingthisprojectwillbenefitin: Graphing their data on a professional graph in minutes

Ability to personalise the graph Ease of set up Constructing the Project Step1: Required Apparatus This example uses potentiometers as the sensors from which we will gather the data but any sensors, digital or analogue can be used. The list of materials is below. 1, Arduino Mega 1, Elegoo 2.8' TFT LCD 1, Breadboard 2, Potentiometers Jumper Wires

All the Components

Step2:Connecting the Circuit The schematics below show how the circuit is wired, just snap on the TFT LCD and connect the potentiometers.

The Schematics Step 3: Acknowledging the Code There are three main parts to the code: Set Up Graph Read Sensor Values Draw Graph These sections are explained below. Set Up Graph // draw title tft.setCursor(10, 10); // set the cursor tft.setTextColor(BLUE); // set the colour of the text tft.setTextSize(3); // set the size of the text tft.println(graphName);

// draw outline tft.drawLine(originX, originY, ((originX + sizeX) - 20), originY, graphColor); tft.drawLine(originX, originY, originX, (originY - sizeY), graphColor); tft.drawLine(originX, originY, (originX + 20), (originY - 20), graphColor); tft.drawLine(((originX + sizeX) - 20), originY, ((originX + sizeX)), (originY - 20), graphColor); tft.drawLine((originX + 20), (originY - 20), (originX + 20), ((originY sizeY) - 20), graphColor); tft.drawLine((originX + 20), ((originY - sizeY) - 20), originX, (originY sizeY), graphColor); tft.drawLine((originX + 20), (originY - 20), ((originX + sizeX)), (originY - 20), graphColor); // draw lables for(int i = 0; i < numberOfMarks; i++) { tft.drawLine(mark[i], originY, mark[i], minorSizeY, graphColor); } // draw lable names for(int i = 0; i < numberOfMarks; i += 2) { tft.setCursor((mark[i] + 6), (originY + 10)); tft.setTextColor(graphColor); tft.setTextSize(2); tft.println(graphBlock[i / 2]); } // draw numbers

for(int i = 0; i < 6; i++) { tft.drawLine(originX, (originY - number[i]), minorSizeX, (originY number[i]), graphColor); } // draw number values for(int i = 0; i < 6; i++) { tft.setCursor((minorSizeX - 30), (number[i] + numberSize)); tft.setTextColor(graphColor); tft.setTextSize(1); tft.println(val[i]); } This section of code draws the outline of the graph and gives it a 3D effect. This is done using the parameters set by the user. Read Sensor Data // get the values of the sensors valueBlock[0] = analogRead(A15); valueBlock[1] = analogRead(A14); This section of code will append 2 analog values to the variables representing the data that will be used to draw the graph. DrawGraph // Erase the previous blocks for(int i = 0; i < 2; i++) { if(posBlock[i] > (prevPosBlock[i] + 2) || posBlock[i] < (prevPosBlock[i] 2) || firstRun) {

tft.fillRect((mark[i * 2] - 1), ((originY - sizeY) - 20), (boxSize + 22), (sizeY + 20), WHITE); } } // Complicated graph redrawing if(valueBlock[0] < 5) { tft.drawLine((originX + 20), (originY - 20), ((originX + sizeX) / 2), (originY - 20), graphColor); } if(valueBlock[1] < 5) { tft.drawLine((((originX + 20) * 2) + 25), (originY - 20), ((originX + sizeX)), (originY - 20), graphColor); } // The main graph drawing loop for(int i = 0; i < 2; i++) { if(posBlock[i] > (prevPosBlock[i] + 2) || posBlock[i] < (prevPosBlock[i] 2) || firstRun) { // start drawing tft.drawLine((mark[(i * 2) + 1]), originY, (mark[(i * 2) + 1] + 20), (originY - 20), BLACK); tft.drawLine((mark[(i * 2)] + 20), (posBlock[i] - 20), mark[(i * 2)], posBlock[i], BLACK); if(valueBlock[i] > 20) {

// draw the bars tft.fillRect((mark[i * 2] + 1), (posBlock[i] + 1), (boxSize - 1), (originY posBlock[i] - 1), blockColor); // Draw 3D Outline tft.drawLine((mark[(i * 2) + 1] + 20), (originY - 20), (mark[(i * 2) + 1] + 20), (posBlock[i] - 20), BLACK); tft.drawLine((mark[(i * 2) + 1] + 20), (posBlock[i] - 20), mark[(i * 2) + 1], posBlock[i], BLACK); tft.drawLine((mark[(i * 2)] + 20), (posBlock[i] - 20), (mark[(i * 2) + 1] + 20), (posBlock[i] - 20), BLACK); tft.drawLine(mark[(i * 2)], posBlock[i], (mark[(i * 2) + 1]), posBlock[i], BLACK); tft.drawLine(mark[(i * 2)], originY, mark[(i * 2)], posBlock[i], BLACK); tft.drawLine(mark[(i * 2) + 1], originY, mark[(i * 2) + 1], posBlock[i], BLACK); // Draw the triangles tft.fillTriangle((mark[(i * 2) + 1] + 1), (originY - 2), ((mark[(i * 2) + 1] + 20) - 1), ((originY - 20) - 1), ((mark[(i * 2) + 1] + 20) - 1), ((posBlock[i] 20) + 2), blockColor); tft.fillTriangle((mark[(i * 2) + 1] + 1), posBlock[i], (mark[(i * 2) + 1] + 1), (originY - 2), ((mark[(i * 2) + 1] + 20) - 1), ((posBlock[i] - 20) + 2), blockColor); tft.fillTriangle((mark[(i * 2) + 1]), (posBlock[i] - 1), ((mark[(i * 2) + 1] + 20) - 2), ((posBlock[i] - 20) + 1), (mark[(i * 2)] + 2), (posBlock[i] - 1), blockColor); tft.fillTriangle((mark[(i * 2)] + 1), (posBlock[i] - 1), ((mark[(i * 2) + 1] + 20) - 2), ((posBlock[i] - 20) + 1), ((mark[(i * 2)] + 20)), ((posBlock[i] 20) + 1), blockColor); } }

} // print value on bars if set for(int i = 0; i < 2; i++) { if(posBlock[i] > (prevPosBlock[i] + 2) || posBlock[i] < (prevPosBlock[i] 2) || firstRun) { prevPosBlock[i] = posBlock[i]; if(displayValues) { tft.setCursor((mark[i * 2] + 5), (originY - 20)); tft.setTextColor(BLACK); tft.setTextSize(2); tft.println(valueBlock[(i *2) / 2]); } } } firstRun = false; This part of code will draw the bars of the graph representing the sensor data collected, fro further information on the exact procedure, refer to Functionality > Drawing the Graph. Personalising the Graph So that is great, we have the graph, but it is always nicer to be able to make it our own, here we will talk about personalising the graph. The lines of code below expose the variables that have to be edited. bool proDebug = false; // TODO - Debugging? ~ true/false - Note - Requires Serial Monitor to be open bool displayValues = true;

// TODO - Display the Values

of the Sensors on the Graph? uint16_t graphColor = BLUE; Outline uint16_t blockColor = GREEN; String graphName = "3D Bar Chart";

// TODO - Colour of Graph // TODO - Colour of Bars // TODO - Title of Graph

String graphBlock[] = {"Pot 1", "Pot 2"}; // TODO - Title of Blocks int graphRange = 1024; // Max Value that the data can get to - Used to map the data - Refer to Tutorial for help setting proDebug enables printing to the serial monitor, its default position is 0 (off), when turned on (1/true), the device requires the serial monitor to be open, it then prints values to the serial monitor, ideal for troubleshooting. displayValues regulates if values should be displayed for each bar or not, when turned on, the value of each sensor is displayed at the bottom of each block, defaults to true. graphColor sets the colour of the graph, the lines and numbers on the x and y axis will be displayed in the selected colour. blockColour sets the colour that the blocks/bars of the chart are displayed in. graphName sets the name of the chart, this is displayed at the top of the graph in blue. graphRange is the highest number that the sensor can output, this number is essential for the graphing and must be set correctly, if you want to display a Raw Analog pin's value, like the potentiometer, set it to 1024, the max value of an Analog pin. If you are using a sensor that outputs a gestured value, like a temperature sensor, you could set the value to a high number like 50. (Note that the chart has not been tested with negative numbers) All of the other values are calculated automatically which means less time to worry about the code and more time to enjoy the graph. Editing Values

As mentioned so many times before, the project can graph any data you give it. At the moment the code is designed to read Analogue pins 14 and 15 and graph those values, but the user can read any analogue pins connected to any sensors and even integrate libraries in the code that provide the data. Adding your own value to the graph is stepped below.

Open the Code

Find line 136 of the main sketch

Change the values to any analogue pin you have your sensors connected to Or to a Loop that extracts your Data from a Library Going Further

You can go further experimenting with the project, try editing the originX, originY, sizeX and sizeY constants to give your graph a different size and position on the screen. There is a header file attached to the main sketch, it contains the colour codes of some colours, try changing the colour of the chart and the bars. And that is it, your personalised graph is ready. Libraries Elegoo Libraries - Copyright (c) 2012 Adafruit Industries under the BSD License Background I have been thinking of building this project after I have published the original Bar Chart project that you can find here. Basically building on that project and making it 3D. It unfortunately is not possible to edit the amount of bars in the chart as the 3D parts of the graph may not look so realistic. Well I got the time to make it now and here it is. Giving everyone the ability to display their data in style, in 3D locally on a TFT LCD, so there is no need to parse the data to a backend and display it there.

A Professional Intro

The graph

SCHEMATICS

CODE

#include // Core graphics library #include // Hardware-specific library #include "Universum_TFTColours.h" // Universum library for colours #define LCD_CS A3 // Chip Select goes to Analog 3 #define LCD_CD A2 // Command/Data goes to Analog 2 #define LCD_WR A1 // LCD Write goes to Analog 1 #define LCD_RD A0 // LCD Read goes to Analog 0 #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin Elegoo_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); // Global Variables int valueBlock[2]; // stores values int posBlock[2]; int prevPosBlock[2]; bool firstRun = true; // Editable Variables bool proDebug = false; Requires Serial Monitor to be open

// TODO - Debugging? ~ true/false - Note -

bool displayValues = true; the Graph? uint16_t graphColor = BLUE; uint16_t blockColor = GREEN; String graphName = "3D Bar Chart"; String graphBlock[] = {"Pot 1", "Pot 2"};

// TODO - Display the Values of the Sensors on

// TODO - Colour of Graph Outline // TODO - Colour of Bars // TODO - Title of Graph // TODO - Title of Blocks

int graphRange = 1024; // Max Value that the data can get to - Used to map the data - Refer to Tutorial for help setting // calculate values const int numberOfMarks = 4; const int originX = 45; const int originY = 200; const int sizeX = 270; const int sizeY = 150; int boxSize = (sizeX / numberOfMarks); int mark[] = {boxSize, (boxSize * 2), (boxSize * 3), (boxSize * 4), (boxSize * 5), (boxSize * 6), (boxSize * 7), (boxSize * 8)}; const int minorSizeY = (originY + 10); const int minorSizeX = (originX - 10); int numberSize = (sizeY / 6); int number[] = {numberSize, (numberSize * 2), (numberSize * 3), (numberSize * 4), (numberSize * 5), (numberSize * 6)}; int numberValue = (graphRange / 6); int val[] = {graphRange, (numberValue * 5), (numberValue * 4), (numberValue * 3), (numberValue * 2), numberValue}; void drawHome() { tft.fillScreen(BLACK); delay(500); tft.setCursor(10, 10); // set the cursor tft.setTextColor(BLUE); // set the colour of the text tft.setTextSize(5); // set the size of the text tft.println("Universum"); tft.setCursor(10, 80); // set the cursor tft.setTextColor(CYAN); // set the colour of the text

tft.setTextSize(3); // set the size of the text tft.println("Graphing"); tft.setCursor(30, 110); // set the cursor tft.setTextColor(CYAN); // set the colour of the text tft.setTextSize(2); // set the size of the text tft.println("3D Bar Charts"); tft.setCursor(10, 160); // set the cursor tft.setTextColor(WHITE); // set the colour of the text tft.setTextSize(2); // set the size of the text tft.println("Andrei Florian"); delay(4000); tft.fillScreen(WHITE); delay(500); } void drawGraph() { // draw title tft.setCursor(10, 10); // set the cursor tft.setTextColor(BLUE); // set the colour of the text tft.setTextSize(3); // set the size of the text tft.println(graphName); // draw outline tft.drawLine(originX, originY, ((originX + sizeX) - 20), originY, graphColor); tft.drawLine(originX, originY, originX, (originY - sizeY), graphColor); tft.drawLine(originX, originY, (originX + 20), (originY - 20), graphColor); tft.drawLine(((originX + sizeX) - 20), originY, ((originX + sizeX)), (originY - 20), graphColor); tft.drawLine((originX + 20), (originY - 20), (originX + 20), ((originY - sizeY) - 20), graphColor); tft.drawLine((originX + 20), ((originY - sizeY) - 20), originX, (originY - sizeY), graphColor); tft.drawLine((originX + 20), (originY - 20), ((originX + sizeX)), (originY - 20), graphColor); // draw lables for(int i = 0; i < numberOfMarks; i++) { tft.drawLine(mark[i], originY, mark[i], minorSizeY, graphColor); }

// draw lable names for(int i = 0; i < numberOfMarks; i += 2) { tft.setCursor((mark[i] + 6), (originY + 10)); tft.setTextColor(graphColor); tft.setTextSize(2); tft.println(graphBlock[i / 2]); } // draw numbers for(int i = 0; i < 6; i++) { tft.drawLine(originX, (originY - number[i]), minorSizeX, (originY - number[i]), graphColor); } // draw number values for(int i = 0; i < 6; i++) { tft.setCursor((minorSizeX - 30), (number[i] + numberSize)); tft.setTextColor(graphColor); tft.setTextSize(1); tft.println(val[i]); } } void graph() { // get the values of the sensors valueBlock[0] = analogRead(A15); valueBlock[1] = analogRead(A14); if(proDebug) { Serial.println(valueBlock[0]); Serial.println(valueBlock[1]); Serial.println(""); } // map the sensor data to the graph size for(int i = 0; i < 2; i++) { posBlock[i] = map(valueBlock[i], 0, graphRange, originY, (originY - sizeY)); } if(proDebug)

{ Serial.println(posBlock[0]); Serial.println(posBlock[1]); Serial.println(""); } // Erase the previous blocks for(int i = 0; i < 2; i++) { if(posBlock[i] > (prevPosBlock[i] + 2) || posBlock[i] < (prevPosBlock[i] - 2) || firstRun) { tft.fillRect((mark[i * 2] - 1), ((originY - sizeY) - 20), (boxSize + 22), (sizeY + 20), WHITE); } } // Complicated graph redrawing if(valueBlock[0] < 5) { tft.drawLine((originX + 20), (originY - 20), ((originX + sizeX) / 2), (originY - 20), graphColor); } if(valueBlock[1] < 5) { tft.drawLine((((originX + 20) * 2) + 25), (originY - 20), ((originX + sizeX)), (originY - 20), graphColor); } // The main graph drawing loop for(int i = 0; i < 2; i++) { if(posBlock[i] > (prevPosBlock[i] + 2) || posBlock[i] < (prevPosBlock[i] - 2) || firstRun) { // start drawing tft.drawLine((mark[(i * 2) + 1]), originY, (mark[(i * 2) + 1] + 20), (originY - 20), BLACK); tft.drawLine((mark[(i * 2)] + 20), (posBlock[i] - 20), mark[(i * 2)], posBlock[i], BLACK); if(valueBlock[i] > 20) { // draw the bars tft.fillRect((mark[i * 2] + 1), (posBlock[i] + 1), (boxSize - 1), (originY - posBlock[i] - 1), blockColor); // Draw 3D Outline tft.drawLine((mark[(i * 2) + 1] + 20), (originY - 20), (mark[(i * 2) + 1] + 20), (posBlock[i]

- 20), BLACK); tft.drawLine((mark[(i * 2) + 1] + 20), (posBlock[i] - 20), mark[(i * 2) + 1], posBlock[i], BLACK); tft.drawLine((mark[(i * 2)] + 20), (posBlock[i] - 20), (mark[(i * 2) + 1] + 20), (posBlock[i] - 20), BLACK); tft.drawLine(mark[(i * 2)], posBlock[i], (mark[(i * 2) + 1]), posBlock[i], BLACK); tft.drawLine(mark[(i * 2)], originY, mark[(i * 2)], posBlock[i], BLACK); tft.drawLine(mark[(i * 2) + 1], originY, mark[(i * 2) + 1], posBlock[i], BLACK); // Draw the triangles tft.fillTriangle((mark[(i * 2) + 1] + 1), (originY - 2), ((mark[(i * 2) + 1] + 20) - 1), ((originY - 20) - 1), ((mark[(i * 2) + 1] + 20) - 1), ((posBlock[i] - 20) + 2), blockColor); tft.fillTriangle((mark[(i * 2) + 1] + 1), posBlock[i], (mark[(i * 2) + 1] + 1), (originY - 2), ((mark[(i * 2) + 1] + 20) - 1), ((posBlock[i] - 20) + 2), blockColor); tft.fillTriangle((mark[(i * 2) + 1]), (posBlock[i] - 1), ((mark[(i * 2) + 1] + 20) - 2), ((posBlock[i] - 20) + 1), (mark[(i * 2)] + 2), (posBlock[i] - 1), blockColor); tft.fillTriangle((mark[(i * 2)] + 1), (posBlock[i] - 1), ((mark[(i * 2) + 1] + 20) - 2), ((posBlock[i] - 20) + 1), ((mark[(i * 2)] + 20)), ((posBlock[i] - 20) + 1), blockColor); } } } // print value on bars if set for(int i = 0; i < 2; i++) { if(posBlock[i] > (prevPosBlock[i] + 2) || posBlock[i] < (prevPosBlock[i] - 2) || firstRun) { prevPosBlock[i] = posBlock[i]; if(displayValues) { tft.setCursor((mark[i * 2] + 5), (originY - 20)); tft.setTextColor(BLACK); tft.setTextSize(2); tft.println(valueBlock[(i *2) / 2]); } } } firstRun = false; } void setup() { if(proDebug)

{ Serial.begin(9600); while(!Serial) {}; } tft.reset(); delay(500); uint16_t identifier = tft.readID(); identifier=0x9341; tft.begin(identifier); tft.setRotation(1); drawHome(); drawGraph(); } void loop() { graph(); delay(200); }

145) Arduino Keyboard Melodies Projet

COMPONENTS AND SUPPLIES SparkFun Pushbutton switch 12mm

×

4

×

1

Jumper wires (generic)

Arduino UNO & Genuino UNO ×

1

×

1

×

1

×

2

×

1

×

1

Breadboard (generic)

Buzzer

Resistor 10k ohm

Resistor 1M ohm

Resistor 221 ohm

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT Our project is a microcontroller that plays different melodies/songs depending on which button you press. Our microcontroller can play the “Jeopardy Theme”, “Mary Had a Little Lamb” and the choruses of “Lonely” by Akon and “All Star” by Smash Mouth. This project was made by Natalie Clark (15) and Ava Baker (14) for an introduction to engineering class. It uses a piezo/buzzer for sound, four resistors (all different ohms), four buzzers and lots of jumper wires. We used an Arduino Uno to make this. If you're into coding, this is the project for you! The breadboard itself is pretty simple but the code is extensive. Customization If you wish, you can also insert your own songs using the melody[] and beat[] functions, so this project is completely customizable. To change a song you have to write down all of the notes (transpose everything into c major) and their beat lengths which will be entered separately. Make sure that you've already defined all the notes that you're using (the equation for calculating note periods is commented into the code). You can also feel free to make the project more complicated, maybe add LEDs that light up when their button is pressed.

SCHEMATICS

CODE

// TONES //Period = 1,000,000(1/frequency) //letter=note #=octave b=flat // note, period, & frequency. #define d3 6803 // 147 Hz #define c4 3830 // 261 Hz #define d4b 3610 // 277 Hz #define d4 3400 // 294 Hz #define e4b 3215 // 311 Hz #define e4 3038 // 329 Hz #define f4 2864 // 349 Hz #define g4b 2703 // 370 Hz #define g4 2550 // 392 Hz #define a4b 2410 // 415 Hz #define a4 2272 // 440 Hz #define b4b 2145 // 466 Hz #define b4 2028 // 493 Hz #define c5 1912 // 523 Hz #define d5b 1805 // 554 Hz #define d5 1703 // 587 Hz #define e5b 1607 // 622 Hz #define e5 1517 // 659 Hz #define f5 1433 // 698 Hz #define g5b 1351 // 740 Hz #define g5 1276 // 784 Hz #define a5b 1204 // 831 Hz #define a5 1136 // 880 Hz #define b5b 1073 // 932 Hz #define b5 1012 // 988 Hz //A special note, 'R', to represent a rest #define R 0

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CORE VARIABLES int speakerOut = 9; //Set up speaker on pin 9 long tempo = 10000; //Set overall tempo int pause = 1000; //Length of pause between individual notes int rest_count = 100; int tone_ = 0; int beat = 0; long duration = 0;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MARY HAD A LITTLE LAMB

//Quarter note = 40 int melody1[] = { b4, a4, g4, a4, b4, b4, b4, R, a4, a4, a4, R, b4, d4, d4, R, b4, a4, g4, a4, b4, b4, b4, b4, a4, a4, b4, a4, g4 }; //Tones/notes int beats1[] = { 40, 40, 40, 40, 40, 40, 40, 2, 40, 40, 40, 2, 40, 40, 40, 2, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 80 }; //Tone/note lengths int MAX_COUNT1 = sizeof(melody1)/2; //Melody length for looping // ALL STAR //Quarter note = 100 int melody2[] = { b4b, g4b, g4b, e4, g4b, g4b, g4b, e4, g4b, g4b, g4b, b4b, R, b4b, d5b, b4, d5b, e5b, g5b, g5b, a5b, g5b, g4b, g4b, a4b, g4b, b4b, a4b, a4b, g4b, a4b, a4b, b4b, e4b, e4b }; //Tones/notes int beats2[] = { 50, 100, 25, 25, 50, 100, 25, 25, 50, 100, 100, 100, 25, 100, 100, 50, 50, 50, 50, 50, 50, 100, 50, 50, 50, 50, 50, 100, 100, 100, 50, 50, 50, 200, 50 }; //Tone/note lengths int MAX_COUNT2 = sizeof(melody2)/2; //Melody length for looping // JEOPARDY //Quarter note = 64 int melody3[] = { c5, f5, c5, f4, c5, f5, c5, c5, f5, c5, a5, g5, f5, e5, d5, d5b, c5, f5, c5, f4, c5, f5, c5, f5, d5, c5, b4b, a4, g4, f4 }; //Tones/notes int beats3[] = { 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 96, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 128, 96, 32, 64, 64, 64, 64, 64 }; //Tone/note lengths int MAX_COUNT3 = sizeof(melody3)/2; //Melody length for looping // LONELY //Quarter note = 84 int melody4[] = { d4, a4, g4b, a4, d4b, a4, g4b, g4, a4, d4b, g4, g4b, g4, a4, b4, a4, a5, a5 }; //Tones/notes int beats4[] = { 84, 168, 63, 21, 84, 168, 32, 32, 32, 84, 63, 32, 32, 32, 32, 168, 84, 84 }; //Tone/note lengths int MAX_COUNT4 = sizeof(melody4)/2; //Melody length for looping

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PLAY TONE void playTone() { //Pulse the speaker to play a tone for a particular duration (so that there is a small break between each note and they don't immediatly follow each other) long elapsed_time = 0; if (tone_ > 0) { //if this isn't a rest beat, while the tone has played less long than 'duration', pulse speaker HIGH and LOW while (elapsed_time < duration) { digitalWrite(speakerOut,HIGH); delayMicroseconds(tone_ / 2); digitalWrite(speakerOut, LOW); delayMicroseconds(tone_ / 2); elapsed_time += (tone_); //Keep track of how long we pulsed }

} else { for (int j = 0; j < rest_count; j++) { delayMicroseconds(duration); } } }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SETUP void setup() { pinMode(speakerOut, OUTPUT); }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // LOOP void loop() { int keyVal = analogRead(A0); Serial.println(keyVal); // PIN ONE (MARY HAD A LITTLE LAMB) if(keyVal >= 1011){ //Only when the 1st button is pressed for (int i=0; i= 990 && keyVal ( '\0' indica che la stringa è FINITA) char password[Lunghezza_Password];//vettore di caratteri per password inserita dall'utente char passAllarme[] = "9856"; //vettore di caratteri che indica la password dell'antifurto byte conta = 0; //variabile contatore unsigned int tempo = 100; //tempo di ritardo per il debounce della tastiera 4*4 #define DEBUG 1 //costante per il debug --> 1=attiva,0=disattiva byte stato = 0; //variabile per lo stato dei case dello switch bool AllarmeAttivo = true; //variabile booleana per indicare se l'allarme è attivo o no byte valPIR=0; /*Fine variabilit*/ void interruzione (void); //prototipo della funzione dell'interrupt sul pin 2 Keypad keypad = Keypad(makeKeymap(tastiera),pinRiga,pinColonna,dim,dim); //oggetto keypad void setup() { lcd.clear();

lcd.begin(16,2); lcd.backlight(); pinMode (led,OUTPUT); pinMode (led1,OUTPUT); digitalWrite(led2,OUTPUT); pinMode(PIR,INPUT); //imposto il pin 2 come input pinMode(BUZZER,OUTPUT); //imposto il pin 3 come output //imposto la velocità di comunicazione seriale a 9600 bit al secondo // attachInterrupt(0,interruzione,RISING); //imposto il pin di interruput,la funzione che deve richiamare e in quale caso si deve attivare (RISING --> sul fronte di salita) }//end setup void loop() { switch(stato) { /*Stato di partenza in cui si chiede la password per abilitare l'antifurto*/ case 0:

digitalWrite(led1,HIGH); lcd.clear(); lcd.print("Digitare PIN: "); while(Pass_Completa == false) { tasto = keypad.getKey(); //lettura del tasto premuto keypad.setDebounceTime(tempo); //tempo di debounce per premuta tasti if(tasto) { password[conta] = tasto; //salvo il tasto premuto nel vettore di caratteri lcd.print(password[conta]); //stampa del tasto premuto delay(100); lcd.clear(); #if DEBUG delay(100); lcd.print(conta); #endif //fine if condizionale del preprocessore lcd.clear(); delay(100); lcd.println(""); conta++; }//end if

if(conta == Lunghezza_Password-1) { password[5] = '\0'; //chiudo la stringa //visualizzo la password per debug #if DEBUG lcd.print("Password "); lcd.clear(); delay(100); lcd.println(password); #endif Pass_Completa = true; //imposto la password a vero per uscire dal ciclo while conta = 0; //imposto la variabile contatore nuovamente a 0 per un possibile nuovo input di password } //end if }//end while lcd.clear();

/*Controllo se la password è corretta tramite "string-compare"*/ if(strcmp(password,passAllarme) == 0 ) { lcd.println("PASSWORD ESATTA!"); //comunico che la password digitata è corretta delay(1000); lcd.clear(); lcd.println("Attivazione"); //comunico che l'antifurto sta per essere attivato stato = 1; //cambio il valore di stato per cambiare case }//end if se la password è corretta else lcd.clear(); lcd.println("PASSWORD ERRATA!");//comunico che la password digitata è errata delay(1000); lcd.clear(); /*Riazzero il vettore caratteri per la password digitata dall'utente*/ for(int i=0;i {0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20}, // ?

// blank Hex 20

{0x7E,0x81,0x99,0xA1,0xA1,0x9E,0x80,0x7E}, // @ {0x3C,0x42,0x81,0x81,0xFF,0x81,0x81,0x81}, // A {0xFC,0x82,0x81,0xFE,0x81,0x81,0x82,0xFC}, // B {0x3C,0x42,0x81,0x80,0x80,0x81,0x42,0x3C}, // C {0xFC,0x82,0x81,0x81,0x81,0x81,0x82,0xFC}, // D {0xFE,0x80,0x80,0xFC,0x80,0x80,0x80,0xFE}, // E {0xFE,0x80,0x80,0xFC,0x80,0x80,0x80,0x80}, // F 70 {0x3C,0x42,0x81,0x80,0x87,0x81,0x42,0x3C}, // G {0x81,0x81,0x81,0xFF,0x81,0x81,0x81,0x81}, // H {0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0xFE}, // I {0xFF,0x08,0x08,0x08,0x08,0x88,0x88,0x70}, // J {0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x84}, // K {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFE}, // L {0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81}, // M {0x81,0xC1,0xA1,0x91,0x89,0x85,0x83,0x81}, // N {0x3C,0x42,0x81,0x81,0x81,0x81,0x42,0x3C}, // O {0xFC,0x82,0x81,0x82,0xFC,0x80,0x80,0x80}, // P 80 {0x3C,0x42,0x81,0x81,0x81,0x85,0x42,0x3D}, // Q {0xFC,0x82,0x81,0x82,0xFC,0x84,0x82,0x81}, // R {0x3C,0x42,0x81,0x40,0x3E,0x81,0x42,0x3C}, // S {0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x10}, // T {0x82,0x82,0x82,0x82,0x82,0x82,0x44,0x38}, // U {0x82,0x82,0x82,0x82,0x82,0x44,0x28,0x10}, // V {0x81,0x81,0x81,0x81,0x99,0xA5,0xC3,0x81}, // W {0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81}, // X {0x82,0x44,0x28,0x10,0x10,0x10,0x10,0x10}, // Y {0xFF,0x02,0x04,0x08,0x10,0x20,0x40,0xFF}, // Z 90 {0xE0,0x80,0x80,0x80,0x80,0x80,0x80,0xE0}, // [ {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}, // {0x07,0x01,0x01,0x01,0x01,0x01,0x01,0x07}, // ] {0xE0,0xA0,0xE0,0xA0,0xAA,0x15,0x15,0x11}, // am (coded as '^' {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E}, // _ {0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00}, // ' {0x00,0x00,0x38,0x04,0x3C,0x44,0x48,0x34}, // a {0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x38}, // b {0x00,0x00,0x18,0x24,0x40,0x40,0x24,0x18}, // c {0x00,0x04,0x04,0x04,0x3C,0x44,0x44,0x38}, // d 100 {0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38}, // e {0x00,0x18,0x20,0x20,0x78,0x20,0x20,0x20}, // f {0x00,0x38,0x44,0x44,0x38,0x04,0x44,0x38}, // g {0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44}, // h {0x00,0x00,0x40,0x00,0x40,0x40,0x40,0x40}, // i {0x00,0x08,0x00,0x08,0x08,0x08,0x48,0x30}, // j {0x00,0x40,0x40,0x48,0x50,0x60,0x50,0x48}, // k {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x20}, // l {0x00,0x00,0x00,0x28,0x54,0x44,0x44,0x44}, // m

{0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44}, {0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38}, {0x00,0x00,0x70,0x48,0x48,0x70,0x40,0x40}, {0x00,0x00,0x30,0x48,0x48,0x38,0x08,0x08}, {0x00,0x00,0x00,0x30,0x48,0x40,0x40,0x40}, {0x00,0x30,0x48,0x40,0x30,0x08,0x48,0x30}, {0x00,0x20,0x70,0x20,0x20,0x20,0x28,0x10}, {0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x38}, {0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10}, {0x00,0x00,0x82,0x82,0x82,0x92,0x54,0x28}, {0x00,0x00,0x84,0x48,0x30,0x30,0x48,0x84}, {0x00,0x48,0x48,0x48,0x38,0x08,0x48,0x30}, {0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x7C}, {0x00,0x30,0x40,0x40,0x80,0x40,0x40,0x30}, {0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20}, {0x00,0x60,0x10,0x10,0x08,0x10,0x10,0x60}, {0xE0,0xA0,0xE0,0x80,0x8A,0x15,0x15,0x11} };

// define RTC operation RTC_DS1307 RTC;

// n 110 // o // p // q // r // s // t // u // v // w // x 120 // y // z // { // | // } // pm codes as '~' Hex 7E, Dec 126

// Tiny RTC (DS1307) module (SDA - A4, SCL - A5)

// rotary encoder, switch and LED control #define enc_PinA 2 // encoder A to pin 2 (interrupt 0) #define enc_PinB 4 // encoder B to pin 4 #define enc_Switch 3 // encoder switch to pin 3 (interrupt 1) #define mode_Pin 8 // mode LED pin #define min_Pin 9 // minute LED pin unsigned char enc_A, enc_B, enc_A_prev=0; static boolean rotating = false; static boolean clockwise = false; static boolean updateFlag= false; static int mode = 0; // 0 - nothing, 1 - hour set, 2 - min set // define display strings #define max_array_size 100 char ac[max_array_size] = {}; byte rc[8] = {}; String display_message = ""; int arraylen;

// operational parameters #define delay_line 75 // ms between line shifts #define delay_char 400 // ms between characters #define delay_mess 500 // ms between messages #define cblanks 1 // number of blank lines between characters #define eblanks 0 // number of additional blank lines (above 8) at the end of the message // display features static boolean top2bottom = false; // display direction (top to bottom, or right to left static boolean hour24 = false; // 24 hour display? static boolean charHI = true; // highlight whole character static boolean doSerial = true;

// serial output?

//************************************************************************************* // Initial Setup //************************************************************************************* void setup () { Wire.begin(); Serial.begin(57600); if(doSerial) Serial.print("MATRIX Clock - Adrian Jones, Mar. 2014"); // 8x8 LED matrix control pins pinMode(dataIn, OUTPUT); pinMode(clock, OUTPUT); pinMode(load, OUTPUT); initMatrix(); // initialize LED matrix // LED pins pinMode(mode_Pin, OUTPUT); digitalWrite(mode_Pin, 1); pinMode(min_Pin, OUTPUT); digitalWrite(min_Pin, 1);

// mode pin // minute pin

// encoder control pinMode(enc_PinA, INPUT_PULLUP); digitalWrite(enc_PinA, HIGH); encoder pin A pinMode(enc_PinB, INPUT_PULLUP); digitalWrite(enc_PinB, HIGH); encoder pin B pinMode(enc_Switch, INPUT_PULLUP);digitalWrite(enc_Switch, HIGH); switch

// rotary // rotary // encoder

attachInterrupt(0, rotEncoder, CHANGE); // time setting attachInterrupt(1, swEncoder, CHANGE); // mins / hours // RTC RTC.begin(); if (! RTC.isrunning()) { RTC.adjust(DateTime(__DATE__, __TIME__)); if(doSerial) Serial.println(" (RTC reset)"); } else { if(doSerial) Serial.println(" (RTC running)"); } }

//************************************************************************************* // Main Loop //************************************************************************************* void loop () { DateTime now = RTC.now(); // show_time_and_date(now); // display time display_message = createMessage(now); arraylen = initDisplayString(display_message); if(updateFlag) { show_time_and_date(now); updateFlag = false; } while(rotating) { delay(1); // debounce adjTime(now, clockwise); show_time_and_date( RTC.now() ); display_message = createMessage(now); arraylen = initDisplayString(display_message); delay(1); rotating = false; // Reset the interrupt flag back to false } delay(5); for (int i = 0; i < (arraylen-7); i++) { // loops through message array, advancing one byte at a time for (int j = 1; j < 9; j++) { maxSingle(j,ac[i+8-j]); } // row 1 gets ac[i+8], row 2 gets ac[i+7] etc... row 8 gets ac[i+0]

if(i%(8+cblanks) == 0) { // when there is a complete character on the display... if(charHI) maxSingle(max7219_reg_intensity, 0x01); // ... increase brightness and temporary halt newDelay(delay_char); } else { // normal brightness maxSingle(max7219_reg_intensity, 0x00); newDelay(delay_line); } } if(mode == 0) newDelay(delay_mess); } // ********************************************************************************** // // INTERRUPT ROUTINES // ********************************************************************************** // // function rotEncoder(): ISR called when encoder rotated void rotEncoder(){ delay(1); enc_A = digitalRead(enc_PinA); enc_B = digitalRead(enc_PinB); if(!enc_A && enc_A_prev){ // change of state clockwise = (!enc_A && enc_B)? true : false; if(mode != 0) rotating = true; } enc_A_prev = enc_A; // Store value of A for next time } // function swEncoder(): ISR called when encoder button pushed void swEncoder(){ delay(1); if(digitalRead (enc_Switch) != LOW) return; // if switch depressed delay(1); // debounce if(digitalRead (enc_Switch) != LOW) return; // if switch still depressed mode++; mode = mode % 3; // increment mode digitalWrite(mode_Pin, !(mode == 1)); // hour adjust LED digitalWrite(min_Pin, !(mode == 2)); // minute adjust LED updateFlag = true; } //

********************************************************************************** // // OPERATION ROUTINES // ********************************************************************************** // // function newDelay void newDelay (int dly) { for (int z=1; z< dly; z++) { delay(1); if(rotating || updateFlag) break; } }

// function initMatrix() : initialization of the MAX7219 registers void initMatrix() { maxSingle(max7219_reg_scanLimit, 0x07); // all 8 columns being used maxSingle(max7219_reg_decodeMode, 0x00); // set to LED matrix (not 7 seg. digit) maxSingle(max7219_reg_shutdown, 0x01); // not in shutdown mode maxSingle(max7219_reg_displayTest, 0x00); // not in display test for (int e=1; e= 25) adj_hrs = 1; } else { // decrement if(adj_hrs == 0) adj_hrs = 24; if(--adj_hrs = 60) adj_mins = 0;

} else { if(--adj_mins < 0) adj_mins = 59; } RTC.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), adj_mins, now.second() )); } }

// function rotChar(char): for character char, transposes bits 90 deg. (top - bottom ==> left right) // and stores results in rc[0] - rc[7]. byte rotChar(char inLetter) { int ind = int(inLetter) - 0x20; for (int col = 0; col < 8; col++) { byte mask = 0x01 1); // put data digitalWrite(load,HIGH); }

// function putByte() : loads data to matrix, MSB to LSB void putByte(byte data) { byte i = 8; byte mask; while(i > 0) { // MSB to LSB mask = 0x01 = 100) Wire.write((uint8_t)0x40);// sends memory address Wire.write((uint8_t)0x00);// sends sent a zero. #else Wire.send((uint8_t)0x40);// sends memory address Wire.send((uint8_t)0x00);// sends sent a zero. #endif Wire.endTransmission();// stop transmitting }

// Send a request for data to the nunchuck // was "send_zero()" static void nunchuck_send_request() { Wire.beginTransmission(0x52);// transmit to device 0x52 #if (ARDUINO >= 100) Wire.write((uint8_t)0x00);// sends one byte #else Wire.send((uint8_t)0x00);// sends one byte #endif Wire.endTransmission();// stop transmitting } // Encode data to format that most wiimote drivers except // only needed if you use one of the regular wiimote drivers static char nunchuk_decode_byte (char x) { x = (x ^ 0x17) + 0x17; return x; } // Receive data back from the nunchuck, // returns 1 on successful read. returns 0 on failure static int nunchuck_get_data() { int cnt = 0; Wire.requestFrom (0x52, 6);// request data from nunchuck while (Wire.available ()) { // receive byte as an integer #if (ARDUINO >= 100) nunchuck_buf[cnt] = nunchuk_decode_byte( Wire.read() ); #else

nunchuck_buf[cnt] = nunchuk_decode_byte( Wire.receive() ); #endif cnt++; } nunchuck_send_request(); // send request for next data payload // If we recieved the 6 bytes, then go print them if (cnt >= 5) { return 1; // success } return 0; //failure } // Print the input data we have recieved // accel data is 10 bits long // so we read 8 bits, then we have to add // on the last 2 bits. That is why I // multiply them by 2 * 2 static void nunchuck_print_data() { static int i = 0; int joy_x_axis = nunchuck_buf[0]; int joy_y_axis = nunchuck_buf[1]; int accel_x_axis = nunchuck_buf[2]; // * 2 * 2; int accel_y_axis = nunchuck_buf[3]; // * 2 * 2; int accel_z_axis = nunchuck_buf[4]; // * 2 * 2; int z_button = 0; int c_button = 0; // byte nunchuck_buf[5] contains bits for z and c buttons // it also contains the least significant bits for the accelerometer data

// so we have to check each bit of byte outbuf[5] if ((nunchuck_buf[5] >> 0) & 1) z_button = 1; if ((nunchuck_buf[5] >> 1) & 1) c_button = 1; if ((nunchuck_buf[5] >> 2) & 1) accel_x_axis += 1; if ((nunchuck_buf[5] >> 3) & 1) accel_x_axis += 2; if ((nunchuck_buf[5] >> 4) & 1) accel_y_axis += 1; if ((nunchuck_buf[5] >> 5) & 1) accel_y_axis += 2; if ((nunchuck_buf[5] >> 6) & 1) accel_z_axis += 1; if ((nunchuck_buf[5] >> 7) & 1) accel_z_axis += 2; Serial.print(i, DEC); Serial.print("\t"); Serial.print("joy:"); Serial.print(joy_x_axis, DEC); Serial.print(","); Serial.print(joy_y_axis, DEC); Serial.print(" \t"); Serial.print("acc:"); Serial.print(accel_x_axis, DEC); Serial.print(",");

Serial.print(accel_y_axis, DEC); Serial.print(","); Serial.print(accel_z_axis, DEC); Serial.print("\t"); Serial.print("but:"); Serial.print(z_button, DEC); Serial.print(","); Serial.print(c_button, DEC); Serial.print("\r\n"); // newline i++; } // returns zbutton state: 1=pressed, 0=notpressed static int nunchuck_zbutton() { return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1; // voodoo } // returns zbutton state: 1=pressed, 0=notpressed static int nunchuck_cbutton() { return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1; // voodoo } // returns value of x-axis joystick static int nunchuck_joyx() { return nunchuck_buf[0]; } // returns value of y-axis joystick static int nunchuck_joyy() { return nunchuck_buf[1]; }

// returns value of x-axis accelerometer static int nunchuck_accelx() { return nunchuck_buf[2]; // FIXME: this leaves out 2-bits of the data } // returns value of y-axis accelerometer static int nunchuck_accely() { return nunchuck_buf[3]; // FIXME: this leaves out 2-bits of the data } // returns value of z-axis accelerometer static int nunchuck_accelz() { return nunchuck_buf[4]; // FIXME: this leaves out 2-bits of the data } int loop_cnt = 0; byte joyx, joyy, zbut, cbut, accx, accy, accz; void _print() { Serial.print("\tX Joy: "); Serial.print(map(joyx, 15, 221, 0, 255)); Serial.print("\tY Joy: "); Serial.println(map(joyy, 29, 229, 0, 255)); } int joyx1 = 129;

// 15 - 221

int joyy1 = 124;

// 29 - 229

void setup() { Serial.begin(9600); nunchuck_setpowerpins(); nunchuck_init(); // send the initilization handshake Serial.println("Wii Nunchuck Ready");

pinMode(3, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(9, OUTPUT); //type(); } void loop() { if ( loop_cnt > 10 ) { // every 100 msecs get new data loop_cnt = 0; nunchuck_get_data(); zbut = nunchuck_zbutton(); joyx = nunchuck_joyx();

// 15 - 221

joyy = nunchuck_joyy();

// 29 - 229

_print(); } loop_cnt++; if (zbut == 1) { type(); zbut = 0; } else { if (joyx > (joyx1 + 20)) { int speed1 = map(joyx - joyx1, 0, 80, 40, 255); speed1 = constrain(speed1, 0, 255); analogWrite(6, 0); analogWrite(9, speed1); }

else if (joyx < (joyx1 - 20)) { int speed2 = map(joyx1 - joyx, 0, 90, 40, 255); speed2 = constrain(speed2, 0, 255); analogWrite(6, speed2); analogWrite(9, 0); } else { analogWrite(6, 0); analogWrite(9, 0); } if (joyy > (joyy1 + 20)) { int speed3 = map(joyy - joyy1, 0, 80, 40, 255); speed3 = constrain(speed3, 0, 255); analogWrite(3, 0); analogWrite(5, speed3); } else if (joyy < (joyy1 - 20)) { int speed4 = map(joyy1 - joyy, 0, 90, 40, 255); speed4 = constrain(speed4, 0, 255); analogWrite(3, speed4); analogWrite(5, 0); } else { analogWrite(3, 0); analogWrite(5, 0); } }

delay(1); } void type() { int rltime = 200; //digitalWrite(6, 1);//origin //digitalWrite(9, 0); //digitalWrite(3, 1); //digitalWrite(5, 0); //delay(1000); //H============== //digitalWrite(3, 0);//wait //digitalWrite(5, 0); //digitalWrite(6, 0); //digitalWrite(9, 0); //delay(250); //digitalWrite(3, 0);//up digitalWrite(5, 1); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(3, 1);//down //digitalWrite(5, 0); delay(250); digitalWrite(3, 0);//wait

digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); //digitalWrite(6, 0);//right digitalWrite(9, 1); delay(rltime); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); //digitalWrite(3, 0);//up digitalWrite(5, 1); delay(250); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(3, 1);//down //digitalWrite(5, 0); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0);

delay(250); //digitalWrite(6, 0);//right digitalWrite(9, 1); delay(rltime); //I======================== digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(3, 0);//up digitalWrite(5, 1); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(6, 0);//right digitalWrite(9, 1); delay(100); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(6, 1);//left

digitalWrite(9, 0); delay(rltime); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(6, 0);//right digitalWrite(9, 1); delay(100); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(3, 1);//down digitalWrite(5, 0); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(6, 0);//right digitalWrite(9, 1); delay(100); digitalWrite(3, 0);//wait

digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(6, 1);//left digitalWrite(9, 0); delay(rltime); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); } Calibrate Turn on the device: Plug in the controller Attach the battery Make sure everything is oriented correctly: the x axis motor should respond to the x axis of the controller, the motors should travel the direction you want them to, etc... - if something seems off, just power everything down and switch some motor wires around. Once everything is working, control should be relatively intuitive: Control direction and speed with the joystick Press the "z" button to spell out "HI" (pre-programmed) Notes Here are a few other things you can try: Use a different controller (maybe an accelerometer for tilt control)

Replace the gear motors with steppers for greater accuracy Make a program to draw pre-programmed pictures Add a tilt mechanism to allow for automatic erasing

SCHEMATICS

CODE #include #if (ARDUINO >= 100) #include #else #include //#define Wire.write(x) Wire.send(x) //#define Wire.read() Wire.receive() #endif static uint8_t nunchuck_buf[6]; // array to store nunchuck data, // Uses port C (analog in) pins as power & ground for Nunchuck static void nunchuck_setpowerpins() { #define pwrpin PORTC3 #define gndpin PORTC2 DDRC |= _BV(pwrpin) | _BV(gndpin); PORTC &= ~ _BV(gndpin); PORTC |= _BV(pwrpin); delay(100); // wait for things to stabilize } // initialize the I2C system, join the I2C bus, // and tell the nunchuck we're talking to it static void nunchuck_init() { Wire.begin(); // join i2c bus as master Wire.beginTransmission(0x52);// transmit to device 0x52 #if (ARDUINO >= 100) Wire.write((uint8_t)0x40);// sends memory address Wire.write((uint8_t)0x00);// sends sent a zero.

#else Wire.send((uint8_t)0x40);// sends memory address Wire.send((uint8_t)0x00);// sends sent a zero. #endif Wire.endTransmission();// stop transmitting } // Send a request for data to the nunchuck // was "send_zero()" static void nunchuck_send_request() { Wire.beginTransmission(0x52);// transmit to device 0x52 #if (ARDUINO >= 100) Wire.write((uint8_t)0x00);// sends one byte #else Wire.send((uint8_t)0x00);// sends one byte #endif Wire.endTransmission();// stop transmitting } // Encode data to format that most wiimote drivers except // only needed if you use one of the regular wiimote drivers static char nunchuk_decode_byte (char x) { x = (x ^ 0x17) + 0x17; return x; } // Receive data back from the nunchuck, // returns 1 on successful read. returns 0 on failure static int nunchuck_get_data() { int cnt = 0; Wire.requestFrom (0x52, 6);// request data from nunchuck while (Wire.available ()) { // receive byte as an integer #if (ARDUINO >= 100) nunchuck_buf[cnt] = nunchuk_decode_byte( Wire.read() ); #else nunchuck_buf[cnt] = nunchuk_decode_byte( Wire.receive() ); #endif cnt++; } nunchuck_send_request(); // send request for next data payload // If we recieved the 6 bytes, then go print them if (cnt >= 5) { return 1; // success } return 0; //failure } // Print the input data we have recieved // accel data is 10 bits long

// so we read 8 bits, then we have to add // on the last 2 bits. That is why I // multiply them by 2 * 2 static void nunchuck_print_data() { static int i = 0; int joy_x_axis = nunchuck_buf[0]; int joy_y_axis = nunchuck_buf[1]; int accel_x_axis = nunchuck_buf[2]; // * 2 * 2; int accel_y_axis = nunchuck_buf[3]; // * 2 * 2; int accel_z_axis = nunchuck_buf[4]; // * 2 * 2; int z_button = 0; int c_button = 0; // byte nunchuck_buf[5] contains bits for z and c buttons // it also contains the least significant bits for the accelerometer data // so we have to check each bit of byte outbuf[5] if ((nunchuck_buf[5] >> 0) & 1) z_button = 1; if ((nunchuck_buf[5] >> 1) & 1) c_button = 1; if ((nunchuck_buf[5] >> 2) & 1) accel_x_axis += 1; if ((nunchuck_buf[5] >> 3) & 1) accel_x_axis += 2; if ((nunchuck_buf[5] >> 4) & 1) accel_y_axis += 1; if ((nunchuck_buf[5] >> 5) & 1) accel_y_axis += 2; if ((nunchuck_buf[5] >> 6) & 1) accel_z_axis += 1; if ((nunchuck_buf[5] >> 7) & 1) accel_z_axis += 2; Serial.print(i, DEC); Serial.print("\t"); Serial.print("joy:"); Serial.print(joy_x_axis, DEC); Serial.print(","); Serial.print(joy_y_axis, DEC); Serial.print(" \t"); Serial.print("acc:"); Serial.print(accel_x_axis, DEC); Serial.print(","); Serial.print(accel_y_axis, DEC); Serial.print(","); Serial.print(accel_z_axis, DEC); Serial.print("\t"); Serial.print("but:");

Serial.print(z_button, DEC); Serial.print(","); Serial.print(c_button, DEC); Serial.print("\r\n"); // newline i++; } // returns zbutton state: 1=pressed, 0=notpressed static int nunchuck_zbutton() { return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1; // voodoo } // returns zbutton state: 1=pressed, 0=notpressed static int nunchuck_cbutton() { return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1; // voodoo } // returns value of x-axis joystick static int nunchuck_joyx() { return nunchuck_buf[0]; } // returns value of y-axis joystick static int nunchuck_joyy() { return nunchuck_buf[1]; } // returns value of x-axis accelerometer static int nunchuck_accelx() { return nunchuck_buf[2]; // FIXME: this leaves out 2-bits of the data } // returns value of y-axis accelerometer static int nunchuck_accely() { return nunchuck_buf[3]; // FIXME: this leaves out 2-bits of the data } // returns value of z-axis accelerometer static int nunchuck_accelz() { return nunchuck_buf[4]; // FIXME: this leaves out 2-bits of the data } int loop_cnt = 0; byte joyx, joyy, zbut, cbut, accx, accy, accz; void _print() { Serial.print("\tX Joy: "); Serial.print(map(joyx, 15, 221, 0, 255)); Serial.print("\tY Joy: "); Serial.println(map(joyy, 29, 229, 0, 255)); } int joyx1 = 129; // 15 - 221 int joyy1 = 124; // 29 - 229 void setup() { Serial.begin(9600);

nunchuck_setpowerpins(); nunchuck_init(); // send the initilization handshake Serial.println("Wii Nunchuck Ready"); pinMode(3, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(9, OUTPUT); //type(); } void loop() { if ( loop_cnt > 10 ) { // every 100 msecs get new data loop_cnt = 0; nunchuck_get_data(); zbut = nunchuck_zbutton(); joyx = nunchuck_joyx(); // 15 - 221 joyy = nunchuck_joyy(); // 29 - 229 _print(); } loop_cnt++;

if (zbut == 1) { type(); zbut = 0; } else { if (joyx > (joyx1 + 20)) { int speed1 = map(joyx - joyx1, 0, 80, 40, 255); speed1 = constrain(speed1, 0, 255); analogWrite(6, 0); analogWrite(9, speed1); } else if (joyx < (joyx1 - 20)) { int speed2 = map(joyx1 - joyx, 0, 90, 40, 255); speed2 = constrain(speed2, 0, 255); analogWrite(6, speed2); analogWrite(9, 0); } else { analogWrite(6, 0); analogWrite(9, 0); } if (joyy > (joyy1 + 20)) { int speed3 = map(joyy - joyy1, 0, 80, 40, 255); speed3 = constrain(speed3, 0, 255);

analogWrite(3, 0); analogWrite(5, speed3); } else if (joyy < (joyy1 - 20)) { int speed4 = map(joyy1 - joyy, 0, 90, 40, 255); speed4 = constrain(speed4, 0, 255); analogWrite(3, speed4); analogWrite(5, 0); } else { analogWrite(3, 0); analogWrite(5, 0); } } delay(1); } void type() { int rltime = 200; //digitalWrite(6, 1);//origin //digitalWrite(9, 0); //digitalWrite(3, 1); //digitalWrite(5, 0); //delay(1000); //H============== //digitalWrite(3, 0);//wait //digitalWrite(5, 0); //digitalWrite(6, 0); //digitalWrite(9, 0); //delay(250);

//digitalWrite(3, 0);//up digitalWrite(5, 1); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(3, 1);//down //digitalWrite(5, 0); delay(250);

digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); //digitalWrite(6, 0);//right digitalWrite(9, 1); delay(rltime); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

//digitalWrite(3, 0);//up digitalWrite(5, 1); delay(250); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

digitalWrite(3, 1);//down //digitalWrite(5, 0); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

//digitalWrite(6, 0);//right digitalWrite(9, 1); delay(rltime);

//I======================== digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

digitalWrite(3, 0);//up digitalWrite(5, 1); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

digitalWrite(6, 0);//right digitalWrite(9, 1); delay(100); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

digitalWrite(6, 1);//left digitalWrite(9, 0); delay(rltime); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(6, 0);//right digitalWrite(9, 1);

delay(100); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250); digitalWrite(3, 1);//down digitalWrite(5, 0); delay(500); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

digitalWrite(6, 0);//right digitalWrite(9, 1); delay(100); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

digitalWrite(6, 1);//left digitalWrite(9, 0); delay(rltime); digitalWrite(3, 0);//wait digitalWrite(5, 0); digitalWrite(6, 0); digitalWrite(9, 0); delay(250);

}

157) Arduino Save Your Life with The Building Collapse Monitor Projet

COMPONENTS AND SUPPLIES Arduino 101 & Genuino 101 ×

1

×

2

×

1

×

2

SparkFun Flex Sensor Buzzer

Resistor 10k ohm

APPS AND ONLINE SERVICES Blynk

Arduino IDE

ABOUT THIS PROJECT Introduction With the development of civil engineering field, we can identify a lot of constructions everywhere. Metal structures, Concrete beams, Multiplatform buildings are some of them. Further, most of us are used to stay in a building or home during most times of the day. But how can we assure that building is safe enough to stay? What if there’s a small crack or over-inclined beam in your building? It would risk a hundreds of lives.

Earthquakes, Soil hardness, Tornadoes and many more things, could be factors for internal cracks and the deviation of the structures or beams from the neutral position. Most of the times we are not aware of the situation of the surrounding structures. Maybe the place everyday we walk in has cracked concrete beams and can collapse at anytime. But without knowing it we are freely going inside. As a solution for this, we need a good method to monitor concrete, wood, metal beams of constructions where we cannot reach. Solution “Structure Analyzer” is a portable device which can be mounted on a concrete beam, metal structure, slabs etc. This device measures the angle and analyze bends where it’s mounted and send the data to mobile app through Bluetooth. This device uses an accelerometer/ Gyroscope to measure the angle in x,y,z planes and flex sensor to monitor the bends. All raw data are processed and information is sent to the mobile app.

3D Model

Circuit Collect the following components. Arduino 101 Board 2 X Flex sensors 2 X 10k Resistors To reduce the number of components Arduino 101 board is used here as it contains an accelerometer and a BLE module. Flex sensors are used to measure the amount of bending as it changes it's resistance when bending. The circuit is a very small one as only 2 resistors and 2 flex sensors needed to be connected. Following diagram shows how to connect a flex sensor to the Arduino board.

One pin of the resistor is connected to the A0 pin of the Arduino board. Follow the same procedure to connect the second flex sensor. Use A1 pin to connect the resistor.

Connect the buzzer directly to the D3 pin and Gnd pin.

Finishing the device After making the circuit, it has to be fixed inside an enclosure. According to the above 3D model, 2 flex sensors have to be placed at the opposite side of the enclosure. Make space for the USB port to program the board and supply the power. As this device is needed to be used for a long period, the best method to supply power is using a fixed power pack.

Mobile App Download and install Blynk from the Android Play Store. Start a new project for Arduino 101. Select the communication method as BLE. Add 1 terminal, 2 buttons and BLE to the interface. Following images show you how to make the interface.

Code files After making the interface on Blynk you will receive an authorization code. Enter that code at the following place. #include #include char auth[] = "**************"; WidgetTerminal terminal(V2);

//Blynk Authorization Code

BLEPeripheral blePeripheral; In the calibration process, current sensor readings are saved in the EEPROM. values(); EEPROM.write(0,flx1); EEPROM.write(1,flx2); EEPROM.write(2,x); EEPROM.write(3,y); EEPROM.write(4,z); terminal.print("Calibration Succesful"); After calibrating, the device will compare the deviation with the threshold values and beeps the buzzer if they exceed the value. values(); if(abs(flex1-m_flx1)>10 or abs(flex2-m_flx2)>10){ terminal.println("Over Bend"); tone(buzzer, 1000); } if(abs(x-m_x)>15 or abs(y-m_y)>15 or abs(z-m_z)>15){ terminal.println("Over Inclined"); tone(buzzer, 1000); } Functionality Stick the device to on the structure needed to be monitored. Stick the 2 flex sensors as well. Supply power to the board using the USB cable. Open the Blynk interface. Connect with the device by touching the Bluetooth icon. Press the calibration button. After calibrating the terminal will show a message as "Successfully Calibrated." Reset the device.

Now it will monitor the structure and notifies you through the buzzer if it deviates of deforms. You can check the angle and bend values at any time by pressing the Status button. This might looks like a small device. But its' uses are priceless. Sometimes we forget to check the condition of our home, office etc, with our busy schedules. But if there is a small problem, it might end like...... But with this device, a hundreds of lives can be saved by informing the small yet dangerous problems in constructions. SCHEMATICS

CODE #include

/*This code file is related to the "Structure Analyzer" which * is a device to maintain the standards and levels of many * types of structures. */ #define BLYNK_PRINT Serial #define flex1 A0 #define flex2 A1 //Define flex sensor and buzzer pins #define buzzer 3 #include "CurieIMU.h" #include #include #include #include #include char auth[] = "**************";

//Blynk Authorization Code

WidgetTerminal terminal(V2); BLEPeripheral blePeripheral; int m_flx1,m_flx2,m_x,m_y,m_z; //values saved in memory int flx1, flx2,x,y,z; //Current readings void values(){ for(int i=0;i10 or abs(flex2-m_flx2)>10){ terminal.println("Over Bend"); tone(buzzer, 1000); } if(abs(x-m_x)>15 or abs(y-m_y)>15 or abs(z-m_z)>15){ terminal.println("Over Inclined"); tone(buzzer, 1000); } tone(buzzer, 0); } /*VO indicates the calibration mode. In this mode the values of sensors * are saved in the EEPROM */ BLYNK_WRITE(V0){ int pinValue = param.asInt(); if (pinValue == 1){ values(); EEPROM.write(0,flx1); EEPROM.write(1,flx2);

EEPROM.write(2,x); EEPROM.write(3,y); EEPROM.write(4,z); terminal.print("Calibration Succesful"); } } /*We can request current deviation values * by pressing the button V1 */ BLYNK_WRITE(V1){ int pinValue = param.asInt(); if (pinValue == 1){ values(); terminal.print("X angle deviation- "); terminal.print(abs(x-m_x)); terminal.println(); terminal.print("Y angle deviation- "); terminal.print(abs(y-m_y)); terminal.println(); terminal.print("Z angle deviation- "); terminal.print(abs(z-m_z)); terminal.println(); terminal.print("Flex 1 deviation- "); terminal.print(abs(flx1-m_flx1)); terminal.println(); terminal.print("Flex 2 deviation- "); terminal.print(abs(flx2-m_flx2)); terminal.println(); } } BLYNK_WRITE(V2){ }

158) KT Arduino VU Meter Projet

COMPONENTS AND SUPPLIES Arduino Nano R3 ×

1

×

4

Resistor 100k ohm

Through Hole Resistor, 22 kohm

×

1

×

2

×

1

Capacitor 100 nF

Alphanumeric LCD, 16 x 2

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT First of all, this project is aiming to entertain those who like the digital VU (Volume Unit) meters and want to build their own version. The project is easy to build, no deep skills required. However, for better sound vs level visual representation you would need some soldering skills. The input level shifter circuit and DC decouplers are required some attention. Please bear in mind that this device is intended to use this way with low-level audio signals. ( < 2Vrms!) The only thing you need to create is to create the left and right level shifter circuit and attach it to your Arduino board. Then load the sourcecode and you are almost ready. Please note that you might need to use separated power supply (separated from your PC) to avoid any kind of ground loop situation with your hifi / pa system! Since Arduino is a sensitive device and lacks of any surge protection, you need to be cautious with ground looping issue. In the below video you can see it's very simple design: Of course, you can build it with I2C LCD driver as well to reduce the required amount of wires. Advantages: Easy to build

Fairly accurate representation of sound level Very good entertaining and for learning purposes Can be driven with low level of audio It is easy to add / attach to existing PA or HiFi system Disadvantages: Linear representation of the volume level (From around -14dB to 0dB) Not accurate enough for true representation for studio or usage where accuracy is essential High update rate can cause screen flickering Low update rate can cause delay in representation

SCHEMATICS

CODE #include byte Bar[8] = { B11111, B00000, B11111, B11111, B11111, B11111, B00000, B11111 };

byte L[8] = { B00111, B01000, B10100, B10100, B10100, B10111, B01000, B00111 }; byte R[8] = { B00111, B01000, B10110, B10101, B10110, B10101, B01000, B00111 }; byte EndMark[8] = { B10000, B01000, B00100, B00100, B00100, B00100, B01000, B10000 }; byte EmptyBar[8] = { B11111, B00000, B00000, B00000, B00000, B00000, B00000, B11111 }; byte peakHoldChar[8] = { B11111,

B00000, B01110, B01110, B01110, B01110, B00000, B11111 }; String main_version = "1.0"; int left, right; //Variables to store and calculate the channel levels const int numReadings = 5; //Refresh rate. Lower value = higher rate. 5 is the defaul int indexL = 0; //Actual channel index int totalL = 0; //Total channel data int maxL = 0; //Maximal level int indexR = 0; int totalR = 0; int maxR = 0; int inputPinL = A1; //Input pin Analog 1 for LEFT channel int inputPinR = A0; //Input pin Analog 0 for RIGHT channel int volL = 0; int volR = 0; int rightAvg = 0; int leftAvg = 0; long peakHoldTime = 1500; //peak hold time in miliseconds long peakHold = 0; int rightPeak = 0; int leftPeak = 0; long decayTime = 0; long actualMillis = 0; LiquidCrystal lcd(11, 10, 7, 6, 5, 4); //lcd configuration void setup() { lcd.begin(40, 2); //Setting up LCD. 16 chars and 2 rows lcd.createChar(1, Bar); lcd.createChar(2, L); lcd.createChar(3, R); lcd.createChar(4, EmptyBar); lcd.createChar(5, EndMark); lcd.createChar(6, peakHoldChar); //Showing loading message and loading bar

String KTAudio = "KTaudio project"; for (int i = 0; i = numReadings) { indexL = 0; left = maxL; maxL = 0; } totalR = analogRead(inputPinR) / 4 - 128; //reducing the detected hum and noise if(totalR > maxR) { maxR = totalR; } indexR++; if (indexR >= numReadings) { indexR = 0; right = maxR; maxR = 0; } volR = right / 3;

if(volR > 14) { volR = 14; } if (volR < (rightAvg - 2)) { if (decayTime < actualMillis) rightAvg--; volR = rightAvg; } else if (volR > (rightAvg + 2)) { volR = (rightAvg + 2); rightAvg = volR; } else { rightAvg = volR; } if (volR > rightPeak) { rightPeak = volR; } drawBar(volR, rightPeak, 1); volL = left / 3; if(volL > 14) { volL = 14; } if (volL < (leftAvg - 2)) { if (decayTime < actualMillis) leftAvg--; volL = leftAvg; } else if (volL > (leftAvg + 2)) { volL = (leftAvg + 2);

leftAvg = volL; } else { leftAvg = volL; } if (volL > leftPeak) { leftPeak = volL; } drawBar(volL, leftPeak, 0); if (decayTime < actualMillis) decayTime = (millis() + 50); if (peakHold < actualMillis) { peakHold = (millis() + peakHoldTime); rightPeak = -1; leftPeak = -1; } } void drawBar(int data, int peakData, int row) { //If the previous peak data is 1 or 0, then not taking care of the value. if (peakData < 2) { peakData = -1; } //First char (idx 0) = R or L //Last (16th) char (idx 15) is the closing mark of the bar. //We have 14 chars to write. for (int col = 1; col < 15; col++) { lcd.setCursor(col, row); if (col < data) { lcd.write(1); //write bar element } else if (peakData == col) {

lcd.write(6); //write the peak marker } else { lcd.write(4); //write "empty" } } }

159) Arduino Aquaneers Projet

COMPONENTS AND SUPPLIES RGB Diffused Common Anode ×

1

×

3

Photo resistor

Arduino UNO & Genuino UNO ×

1

NECESSARY TOOLS AND MACHINES 3D Printer (generic)

APPS AND ONLINE SERVICES Arduino IDE

openScad

ABOUT THIS PROJECT The Aquaneers project is a feat of aquarium engineering. We aim to create a full suite of monitoring sensors and actuation tools, and incorporating these into the XOD framework. Chemical sensing can be done electronically. There are electronic pH sensors readily available, and the ionic content of water can be measured with a conductivity sensor. Many water quality tests (e.g. ammonia content, nitrate content) involve adding an indicator chemical to a sample and observing the colour. We have built a sensor to measure the transmission and reflection of different colours in a water sample. This is usable for many aquarium water quality measurements, and any other biological or chemical measurement resulting in a change of colour.

Colour sensor

Colour sensor

Colour sensor We aim to build tools for dispensing food, and tools for adding chemicals with quantities, and timing controllable via a touchscreen interface. This display will also show recent water quality measurements, and advise on any necessary human intervention.

SCHEMATICS

CODE #define redLED 3

#define greenLED 6 #define blueLED 5 /* Note the colours of the sensors below correspond to the wire colours used in my build*/ #define yellowSensor 0 #define purpleSensor 1 #define pinkSensor 2 #define delayTime 100 struct SensorReading{ int pink; int yellow; int purple; };

void setup() { // put your setup code here, to run once: pinMode(redLED, OUTPUT); pinMode(greenLED, OUTPUT); pinMode(blueLED, OUTPUT); digitalWrite(redLED, HIGH); digitalWrite(greenLED, HIGH); digitalWrite(blueLED, HIGH); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: SensorReading s; char buffer[200]; redOn(); delay(delayTime); readSensors(s); sprintf(buffer, "Red %d %d %d",s.pink, s.purple, s.yellow); Serial.println(buffer); greenOn(); delay(delayTime); readSensors(s);

sprintf(buffer, "Green %d %d %d",s.pink, s.purple, s.yellow); Serial.println(buffer); blueOn(); delay(delayTime); readSensors(s); sprintf(buffer, "Blue %d %d %d",s.pink, s.purple, s.yellow); Serial.println(buffer); whiteOn(); delay(delayTime); readSensors(s); sprintf(buffer, "White %d %d %d",s.pink, s.purple, s.yellow); Serial.println(buffer); delay(5000); }

void redOn(){ digitalWrite(redLED, LOW); digitalWrite(greenLED, HIGH); digitalWrite(blueLED, HIGH);} void greenOn(){ digitalWrite(redLED, HIGH); digitalWrite(greenLED, LOW); digitalWrite(blueLED, HIGH);} void blueOn(){ digitalWrite(redLED, HIGH); digitalWrite(greenLED, HIGH); digitalWrite(blueLED, LOW);} void whiteOn(){ digitalWrite(redLED, LOW); digitalWrite(greenLED, LOW); digitalWrite(blueLED, LOW);} void readSensors(SensorReading& s ){ s.pink = analogRead(pinkSensor); s.purple = analogRead(purpleSensor); s.yellow= analogRead(yellowSensor); }

160) Arduino Serial Pong Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

Single Turn Potentiometer- 10k ohms ×

2

×

1

×

1

Jumper wires (generic)

Breadboard (generic)

Capacitor 100 µF

ABOUT THIS PROJECT This is a two-player game of Pong played by rotating two potentiometers, just like the original! The potentiometers are connected to an Arduino, which sends the values over serial. A Python script is running on the PC that reads the serial data and updates the game. The script uses the Curses library to make printing a game in an x, y coordinate system within a console easier. The potentiometers determine the Y-position within the console and the ball moves

automatically based on the Arduino's clock. The ball bounces off of each of the paddles, and the script ends when the ball gets past one of the paddles. When the script ends the winner is reported.

SCHEMATICS

CODE Python code # Imports import serial import curses # Constants HEIGHT = 24 WIDTH = 80 BALL_CHAR = '*' PADDLE_CHAR = '|' PADDLE_HEIGHT = 4 GAME_SPEED = 100 # Classes class Timer: def __init__(self, initial_time, target_time): self.last_reset_time = initial_time self.target_time = target_time self.elapsed_time = 0 self.times_reset = 0

def check(self, current_time): self.elapsed_time = current_time - self.last_reset_time if self.elapsed_time >= self.target_time: self.reset(current_time) return True else: return False def reset(self, current_time): self.last_reset_time = current_time # Functions def map(val, in_min, in_max, out_min, out_max): return int((val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min) def read_serial(device): #Read serial data raw_line = device.readline() line = str(raw_line) line = line[2:] #Remove the unicode characters line = line[:-5] #Remove the cariage return and newline from the end of the string data = line.split(" ") #Convert parsed strings into integers try: time = int(data[0]) p1_pot = int(data[1]) p2_pot = int(data[2]) return time, p1_pot, p2_pot, True except: return -1, -1, -1, False def update_game(left_paddle_x, left_paddle_y, right_paddle_x,

right_paddle_y, ball_x, ball_y, dx, dy, update_ball): game_lost = False loss_message = "No one has lost" if update_ball: #Update ball's position based on the x and y velocities ball_x = ball_x + dx ball_y = ball_y + dy # Check to see if the ball has hit the right wall if ball_x >= WIDTH - 1: ball_x = WIDTH - 1 game_lost = True loss_message = "Player 1 won! Player 2 is pretty sucky though..." # Check to see if the ball has hit the left wall if ball_x = right_paddle_y) and (ball_y = (HEIGHT - 1): ball_y = HEIGHT -1 dy = -dy # Check to see if the ball hit the top wall if ball_y = (HEIGHT - PADDLE_HEIGHT): right_paddle_y = (HEIGHT - PADDLE_HEIGHT) # Erase old game screen.clear() # Draw new paddles for i in range(PADDLE_HEIGHT): screen.addch(left_paddle_y + i, left_paddle_x, PADDLE_CHAR) screen.addch(right_paddle_y + i, right_paddle_x, PADDLE_CHAR) # Draw new ball screen.addch(ball_y, ball_x, BALL_CHAR) screen.refresh() return ball_x, ball_y, dx, dy, game_lost, loss_message # Start main program try: serial_device = serial.Serial('/dev/ttyACM0', 9600) serial_device.readline() except: print("No serial device found") exit() # Initilize timer after serial comminications have reset initial_time, initial_pot, temp_bool, temp_string = read_serial(serial_device) # timer_initialized = False

# while not timer_initialized: # initial_time, initial_pot, temp_bool, temp_string = read_serial(serial_device) # if initial_time == 0: # timer_initialized = True timer = Timer(initial_time, GAME_SPEED) # Initialize game variables screen = curses.initscr() screen.refresh() ball_x = int(WIDTH / 2) ball_y = int(HEIGHT / 2) left_paddle_x = 6 left_paddle_y = int(HEIGHT / 2) right_paddle_x = WIDTH - 7 right_paddle_y = int(HEIGHT / 2) ball_dx = 3 ball_dy = 2 game_lost = False while not game_lost: time, p1_pot, p2_pot, data_received = read_serial(serial_device) if data_received: left_paddle_y = map(p1_pot, 0, 1023, 0, HEIGHT - 1) right_paddle_y = map(p2_pot, 0, 1023, 0, HEIGHT - 1) is_time_elapsed = timer.check(time) # Update game ball_x, ball_y, ball_dx, ball_dy, game_lost, loss_message = update_game(left_paddle_x, left_paddle_y, right_paddle_x, right_paddle_y, ball_x, ball_y, ball_dx, ball_dy, is_time_elapsed) curses.endwin() print(loss_message)

Arduino code int player1_val; int player2_val; const int player1_pot = A0; const int player2_pot = A1; void setup() { pinMode(player1_pot, INPUT);

pinMode(player2_pot, INPUT); Serial.begin(9600); } void loop() { player1_val = analogRead(player1_pot); player2_val = analogRead(player2_pot); Serial.print(millis()); Serial.print(" "); Serial.print(player1_val); Serial.print(" "); Serial.println(player2_val); }

161) Record and Play Arduino 3D Printed Robotic ARM Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

4

SG90 Micro-servo motor

Rotary potentiometer (generic)

×

4

NECESSARY TOOLS AND MACHINES 3D Printer (generic)

Soldering iron (generic)

ABOUT THIS PROJECT This is the second version of my 3D printed robotic arm wich is now capable to performs a pre-recorded task many times like a real industrial machine. It contains 4pcs. cheap SG 90 servo motors that are powered by the Arduino board. You can download.stl files for 3D printing from the link given below, or directly to Thingiverse web : https://www.thingiverse.com/thing:1015238. This time I slightly modified the Aswinth Raj code to fit 4 servo motors instead of 5. After we upload the code to the Arduino board, first we need to start Arduino serial monitor and press "R" + Enter to record some job. Now we do the job with the help of potentiometers. Next on the serial monitor we need to press "P" + Enter to execute pre-reloaded job. This job can be performed many times as we require it.

SCHEMATICS

CODE #include //Servo header file //Declare object for 5 Servo Motors Servo Servo_0; Servo Servo_1; Servo Servo_3; Servo Gripper; //Global Variable Declaration int S0_pos, S1_pos, S3_pos, G_pos; int P_S0_pos, P_S1_pos, P_S3_pos, P_G_pos; int C_S0_pos, C_S1_pos, C_S3_pos, C_G_pos; int POT_0,POT_1,POT_3,POT_4; int saved_data[700]; //Array for saving recorded data int array_index=0; char incoming = 0; int action_pos; int action_servo; void setup() { Serial.begin(9600); //Serial Monitor for Debugging //Declare the pins to which the Servo Motors are connected to Servo_0.attach(3); Servo_1.attach(5); Servo_3.attach(9); Gripper.attach(10); //Write the servo motors to initial position Servo_0.write(90); Servo_1.write(90); Servo_3.write(90); Gripper.write(90); Serial.println("Press 'R' to Record and 'P' to play"); //Instruct the user }

void Read_POT() //Function to read the Analog value form POT and map it to Servo value { POT_0 = analogRead(A0); POT_1 = analogRead(A1); POT_3 = analogRead(A3); POT_4 = analogRead(A4); //Read the Analog values form all five POT S0_pos = map(POT_0,0,1024,10,170); //Map it for 1st Servo (Base motor) S1_pos = map(POT_1,0,1024,10,170); //Map it for 2nd Servo (Hip motor) S3_pos = map(POT_3,0,1024,10,170); //Map it for 4th Servo (Neck motor) G_pos = map(POT_4,0,1024,10,170); //Map it for 5th Servo (Gripper motor) } void Record() //Function to Record the movements of the Robotic Arm { Read_POT(); //Read the POT values for 1st time //Save it in a variable to compare it later P_S0_pos = S0_pos; P_S1_pos = S1_pos; P_S3_pos = S3_pos; P_G_pos = G_pos; Read_POT(); //Read the POT value for 2nd time if (P_S0_pos == S0_pos) //If 1st and 2nd value are same { Servo_0.write(S0_pos); //Control the servo if (C_S0_pos != S0_pos) //If the POT has been turned { saved_data[array_index] = S0_pos + 0; //Save the new position to the array. Zero is added for zeroth motor (for understading purpose) array_index++; //Increase the array index } C_S0_pos = S0_pos; //Saved the previous value to check if the POT has been turned } //Similarly repeat for all 5 servo Motors if (P_S1_pos == S1_pos) { Servo_1.write(S1_pos); if (C_S1_pos != S1_pos) { saved_data[array_index] = S1_pos + 1000; //1000 is added for 1st servo motor as

differentiator array_index++; } C_S1_pos = S1_pos; }

if (P_S3_pos == S3_pos) { Servo_3.write(S3_pos); if (C_S3_pos != S3_pos) { saved_data[array_index] = S3_pos + 3000; //3000 is added for 3rd servo motor as differentiater array_index++; } C_S3_pos = S3_pos; } if (P_G_pos == G_pos) { Gripper.write(G_pos); if (C_G_pos != G_pos) { saved_data[array_index] = G_pos + 4000; //4000 is added for 4th servo motor as differentiator array_index++; } C_G_pos = G_pos; } //Print the value for debugging Serial.print(S0_pos); Serial.print(" "); Serial.print(S1_pos); Serial.print(" "); Serial.print(S3_pos); Serial.print(" "); Serial.println(G_pos); Serial.print ("Index = "); Serial.println (array_index); delay(100); } void Play() //Functon to play the recorded movements on the Robotic ARM {

for (int Play_action=0; Play_action 1) //If something is received from serial monitor { incoming = Serial.read(); if (incoming == 'R') Serial.println("Robotic Arm Recording Started......"); if (incoming == 'P') Serial.println("Playing Recorded sequence"); } if (incoming == 'R') //If user has selected Record mode Record();

if (incoming == 'P') //If user has selected Play Mode Play(); }

162) Arduino IR Thermometer Stopwatch Coking Timer Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

Adafruit MLX90614 Microchip AVR for Arduino 328P/168P/8A

×

1

×

1

×

1

SparkFun 7-Segment Serial Display - Red 3 digit display used

×

1

×

2

×

1

×

1

×

1

×

1

×

1

×

1

×

1

Breadboard (generic) 8x2 cm

16 MHz Crystal

Slide Switch

30 mm Red Push Switch any big red push switch 22 mm White Push Switch Buzzer

Colored pin header (generic) MLX90614 IR Temperature Sensor LED Dot Laser (generic)

USB A Connector AMS1117 3.3V Voltage Regulator 150 mAH 3.7V LiPo battery cylindrical

×

1

×

1

×

1

×

1

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT Idea This is a story about making an pocket carry-able USB stick like IR Thermometer made using Arduino programming and some other stuff. The device will also have stopwatch function, kitchen timer and inactivity tracker function. IR Thermometer is an IR radiation-based temperature sensing device which allows for the measurement of the average temperature of a surface it's facing - most probably with Wien's displacement law or Stefan– Boltzmann law from highs school physics. A stopwatch is a basic time measurement device used in sports, scientific experiment, etc. to measure lapsed time. Today, hardware stopwatches (the analog type) are kind of extinct and replaced by a so-called smartphone app. A kitchen timer is a device that alerts cook by buzzing an alarm set such that something being cooked needs checking. An inactivity tracker is a periodic timer that alerts a person to move after every X amount of time. This helps one to get a minute break from idle state and practice healthy life. Hardware Description The finished device looks like this:

Device Top

Bottom Here is a nice description picture of the thing:

Description Making The Thing! Step 1: Gather all the ingredients, imagine and make a mental map of what goes where! Take measurements, make necessary holes, place components and solder.

Tops

bottoms Step 2: Use heat shrink tube and 0 Ohm resistors to interconnect things, 1k resistors on display segment pins, and solder according to the schematic.

Internal Layer

Step 3: Interconnect both layers.

Connecting Sensor layer with UI layer Step 4: Upload test code and check if everything operates. If so, align top and bottom layer with toothpicks and warp on both ends with thin tape. Now, fill the gap with the hot glue and wait 5 minutes. Now, your sturdy device is ready to roll.

Hot glued ! Writing the Software Here, we will use our good old friend, Arduino IDE, to write the program. Before we get into code, let's get an idea how the hardware connections affect the code. The small white momentary push button is the menu selector switch which is interrupt driven; the same goes for the big red push button - connected for falling edge INT 0 and INT 1 on Digital Pin 2 and 3. Digital pin 4 is the buzzer driver pin and A0 is the laser driver pin. A1, A2, A3 are display digit pins; pins 5-12 are segment pins. A4, A5 Digital Pins are for I2C communication with the IR sensor. Finally, thanks to Dean Reading for the Arduino 7-Segment Library and Limor Fridge for the Arduino MXL90614 Library - life made easy! Based on their library example, the basic code is developed - right now only Ambient and Object Temperature detection function is enables. I will add the other functions soon! So, stay tuned. Action! Here are some temperature measurement results photo and a video -

enjoy!

Fridge wall temperature

Room Temperature

Note! The IR Sensor has 90 degree field of view, which means it is not measuring the temperature of the point where the laser pointer is shining, rather it is averaging the temperature of objects on its view plane. The system runs with 4.2 volt fully charged Li-Po battery and should operate with at least 3.7 volts without worries. Laser is directly driven from MCU pin and buzzer is driven through transistor. One of the digital pin powers the 3.3V regulator and the IR sensor. 11 pins are required to direct drive the 7 segment display. The device is rechargeable from the USB port of PC/Laptop. From the USB, 5 volts are reduced to 4.2 with a diode and a resistor in series - simple charging circuit where the blue LED glows while charging. The program can be updated through the 3 blue male header pins (Reset,RX,TX) connected through the external USB-FTDI (serial) device, which is detected as Adruino in Arduino IDE.

SCHEMATICS

CODE // Thanks to Lady Ada and Read for MLX90614 and Sevseg library ! #include "SevSeg.h" #include #include

#define PIN_PWR_SENESOR 13 #define PIN_PWR_LASER A0 #define PIN_PRESS_SWITCH1 2 #define PIN_PRESS_SWITCH2 3 #define PIN_BUZZER_ALERM 4 Adafruit_MLX90614 mlx = Adafruit_MLX90614(); SevSeg sevseg; //Instantiate a seven segment controller object

volatile int test =0; volatile int test2 = 0; float T_amb; float T_obj;

void setup() { pinMode(PIN_PRESS_SWITCH1, INPUT_PULLUP); attachInterrupt(0, SW1, FALLING);// Interrupt for Swithc 1 pinMode(PIN_PRESS_SWITCH2, INPUT_PULLUP); attachInterrupt(1, SW2, FALLING);// Interrupt for Swithc 2 pinMode(PIN_PWR_SENESOR, OUTPUT); pinMode(PIN_PWR_LASER, OUTPUT); pinMode(PIN_BUZZER_ALERM, OUTPUT); digitalWrite(PIN_PWR_SENESOR,HIGH); // powers the regulator + IR sensor digitalWrite(PIN_PWR_LASER,LOW); digitalWrite(PIN_BUZZER_ALERM,LOW); byte numDigits = 3; byte digitPins[] = {A1, A2, A3}; byte segmentPins[] = {11, 9, 7, 6, 5, 10, 8, 12}; bool resistorsOnSegments = false; // Use 'true' if on digit pins byte hardwareConfig = COMMON_ANODE; // See README.md for options sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments); sevseg.setBrightness(100); mlx.begin(); }

void loop() { static unsigned long timer = millis(); static int seconds = 0; if (millis() >= timer) { seconds++; // 100 milliSeconds is equal to 1 deciSecond timer += 1000; if (seconds == 100000) { // Reset to 0 after counting for 1000 seconds. seconds=0; } sevseg.setNumber(T_obj, 1); } if(test==0) { // T_amb = mlx.readAmbientTempC(); T_obj = mlx.readObjectTempC(); sevseg.setNumber(T_obj, 0); sevseg.refreshDisplay(); sevseg.refreshDisplay(); sevseg.refreshDisplay(); sevseg.refreshDisplay(); // Must run repeatedly } if (test==1) { T_amb = mlx.readAmbientTempC(); // T_amb=T_amb*10; sevseg.setNumber(T_amb, 1); sevseg.refreshDisplay(); sevseg.refreshDisplay(); sevseg.refreshDisplay(); sevseg.refreshDisplay(); // Must run repeatedly

} } void SW1() { test=1; digitalWrite(PIN_PWR_Laser,HIGH); } void SW2() { test=0; digitalWrite(PIN_PWR_Laser,HIGH);}

163) Arduino External S Meter On Icom Radios with CI-V Port Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

Single Turn Potentiometer- 10k ohms

×

1

×

1

Resistor 10k ohm ×

1

×

1

×

1

×

1

×

2

×

1

×

1

Resistor 4.75k ohm

Diode 1N4148 Capacitor 10 µF

Ferrite Core Round Cable

Connector 3.5 mm (1/8) Connector Icom tuner (computer supply)

ABOUT THIS PROJECT This circuit uses an Arduino Uno or Nano to send a CI-V command to an Icom radio to ask for signal information, read the answer, convert it and display it on an analog output, where you can connect an analog (Arsonval) S-meter. It is powered by the Antenna Tuner port on the Icom radio. If your Icom does not have a tuner port, you can use any other port or connector that provides a +12V output (at least 200 mA). An external DC power source can also be used. If you don't have an Antenna Tuner connector, you can use a PC computer power supply connector, and trim it with cutters to fit the Icom tuner connector. This project is designed for an Icom IC-7000 transceiver, but it can be adapted to any Icom radio with a CI-V port. You can use the CI-V "00" universal address on some Icom radios, making this converter compatible with any Icom radio, without changing the CI-V address in the code. Ferrites are installed on input & output cables to eliminate RF induction. The +12 V DC to the S-meter is not necessary; it could be used to power meter backlight or any other optional features. The 10 k ohms potentiometer is used to attenuate the signal output (which is too high for most analog meters) and calibrate the analog meter to get a full scale reading with a powerful local signal (+60 dB).

SCHEMATICS

CODE #include // for comms to IC7000 #define BAUD_RATE 19200 // CI-V speed #define TRX_address (0x70) // HEX $70 = Icom IC-7000 //#define TRX_address ((byte)00) // $00: Icom universal address (works for all radios). // serial connection // RX = Icom radio to Arduino : to pin 2 via resistor 4k7 // TX = Arduino to Icom radio : to pin 7 via diode 1N4148, with pull up 10k to Vcc (5V) on tip of 3.5 mm connector SoftwareSerial mySerial = SoftwareSerial(2, 7); // (RX, TX) int readCounter; // counts the number of bytes received from the radio int sMeterVal1; // stores the most significant BCD byte containing signal info. int sMeterVal2; // stores the least significant BCD byte containing signal info. int sMeterOut = 11; // External analog S-meter connected to pin 11. //--------------------------------------------------------------------------------------------void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); // force LED (pin 13) to turn off. pinMode(2, INPUT); // CI-V serial communication from IC7000 pinMode(7, OUTPUT); // CI-V serial communication to IC7000 pinMode(sMeterOut, OUTPUT); // set sMeterPin for output mySerial.begin(BAUD_RATE); mySerial.listen(); // only one port can be made to listen with software serial // see reference https://www.arduino.cc/en/Reference/SoftwareSerialListen while (mySerial.available()) mySerial.read(); // clean buffer }

//--------------------------------------------------------------------------------------------void loop() { // read and display S-meter value mySerial.flush(); // start sequence: send "read S meter" command to radio. mySerial.write(0xFE); mySerial.write(0xFE); mySerial.write(TRX_address); mySerial.write(0xE0); mySerial.write(0x15); mySerial.write(0x02); // Read s-meter , command 15 02 mySerial.write(0xFD); // end sequence delay(20); // now read info from radio int nbChar = mySerial.available(); if (nbChar > 0) { for (int readCounter = 0; readCounter < nbChar ; readCounter++) { byte byteRead = mySerial.read(); if (readCounter == 6){ sMeterVal1 = ( (byteRead/16*10) + (byteRead%16) ); // First byte: convert from BCD to decimal. } if (readCounter == 7){ sMeterVal2 = ( (byteRead/16*10) + (byteRead%16) ); // Second byte: convert from BCD to decimal. analogWrite(sMeterOut, ((sMeterVal1 * 100) + sMeterVal2)); // Calculate and write the Smeter value on the S-meter output pin. delay(20); } } } }

164) Arduino Electric Bike Projet

COMPONENTS AND SUPPLIES Arduino Micro & Genuino Micro ×

Motor Heat Sink w/Fan Red

1

Aluminum (27mm) Female XT60 Connectors

Male XT60 Connectors 24AWG Silicone Wire 6mm Wire Mesh Guard 3 Function Switch w/UBEC, Voltage Display Female JST Battery Pigtail Male JST Battery Pigtail LED Strip with JST Female Connector 200mm (Red) Round 2-Way Switch (Short) Police Car LED Lighting System JST-SH Servo Plug Set

×

1

×

5

×

5

×

1

×

1

×

1

×

5

×

5

×

1

×

1

×

1

×

1

Ultrasonic Sensor - HC-SR04 (Generic)

×

1

LM386 Audio Amplifier Module with 10K Resistance

×

1

×

1

×

1

DPDT 6 Terminal 2 Position Rocker Switch

×

1

20 Wire Rainbow Color Flat Ribbon Cable

×

1

×

1

×

1

×

3

MicroSD Module 12mm Push Button Switch

Micro-USB to USB Cable (Generic)

USB Female Socket Connector with Plastic Cover Female Header 8 Position 1 Row (0.1") Need pieces of 20 positions Right Angle Single Row Female

Header Male Header 40 Position 1 Row (0.1")

Dupont Connector Kit 10x5cm Prototype Board 2S LiFe Battery 2S LiPo Battery Spade Wire Connector

×

1

×

1

×

1

×

1

×

1

×

1

×

1

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

Pliers Wire Stripper

APPS AND ONLINE SERVICES Arduino IDE

Audacity ABOUT THIS PROJECT Original bike had forward/reverse control and 2 push buttons for prerecorded audio playback (honk the horn and bike start sound effect). I got rid of all original electronics including speaker, lead-acid battery and buttons (including the 3 position rocker switch). I kept the 6V DC motor and the original powertrain wire harness (had to do some rewire though). With some planning and creativity I ended up with the following features: new ON/OFF switch for electronics automatically triggers startup sound (no more button for that) rear proximity sensor automatically enabled when reverse is engaged police siren with 3 modes (lights only, quick siren, loop mode) horn (or ability to play other sound effects/music) bottom led strip for "fast and furious" mode Having all features in mind it was time to design the PCB and order required parts. A mono audio amplifier was needed to drive the new speaker. For audio file storage we are using a MicroSD card module. The police LED lightning system comes from RC car toys. It's supposed to work with servo protocol but after some tinkering I could manage to make it work with standard Arduino functions. For the PCB I found 10cm x 5cm a perfect fit for our bike electronics bay. All connections to external modules and wires are made thru pin

headers (males or females, straight or right angle). Blue wires are external jumpers in the top of the board while copper wires are soldered track on the bottom.

Current PCB design Connections done as follow (from top to bottom, left to right): 3 vertical male pins, straight: police LED flashing system 4 vertical male pins, straight: parking sensor 4 series of 2 vertical male pins, straight: horn BT, siren BT, reverse signal, siren SW 4 horizontal female pins, straight: audio amplifier 2 horizontal male pins, straight: power source (Vin and GND) 6 horizontal female pins, right angle: MicroSD module

Early stages of PCB (bottom part)

Early stages of PCB (top part), button connections were swapped later There is no need to connect the LED strip to the Arduino board, so the second mini switch is connected directly to the power train line (switch cuts Vcc). Talking about power, it was necessary to have 2 power lines (while sharing the same ground) separated: the one I call the power train power line (for DC motor and LED strip) and the electronics power line (for motor cooling fan, Arduino and it's modules). The first one is powered by a 6,6V 2S LiFe battery and the later is powered by a 7,4V 2S LiPo battery (or anything else in the range of the UBEC). The 3 function switch with UBEC lies in between the battery and the electronics power line and is set to regulate output voltage to 5,2V.

Please note that although I have made header pins for Arduino's Vin and GND, they are unused. Arduino power comes from a micro USB cable routed to under seat compartment because electronics power line delivers only 5V (plugging it to Vin would cause Arduino's own regulator to drop voltage even more and the other modules would starve). This has the benefit of making easier software updates: just unplug the USB from below the seat and plug into your computer. The original 3 position rocker switch (Forward/Off/Reverse) was replaced for a 2 position rocker switch (Forward/Reverse). I had to do some rewiring to be able to signal Arduino when reverse is selected. This is done by tapping into the ground wire of the reverse position in switch and connecting it in the reverse signal pin in our PCB. I also added a diode so we don't harm our Arduino when this pin is shorted with Vcc (at Forward position).

Powertrain rewired Many different connectors were used to make custom cables for all necessary wiring. The police lighting system, cooling fan and the LED strip have JST plugs. The power switch has a JST (input) and a servo connector (output). My batteries have XT60 and JST plugs. We also need a female USB to drive power to the Arduino board. Please see the parts list for all parts I have used.

under the seat bay Bear in mind that our DC motor is 6V only but we are powering it with a 6,6V (nominal voltage) battery that can reach more than 7V when fully charged. The extra power can make things very hot at our engine so I installed a heatsink with a 5V fan. The fact it's 5V is the reason why the fan is connected to the electronics power line and not the powertrain. You can see the fan in the middle left of the picture above. Initially I considered to power the electronics with a 9V battery but adding the fan to this power line depleted the battery in a matter of a few minutes. That's why I replaced it later for a 2S Lipo (properly protected with a lipo bag and a low voltage alarm).

Electronics bay Electronics bay is located under the bike, it's a little tight in there but with patience you can fit everything in place. Speaker is installed in the bay cover (same place as the original speaker). Bay cover is shown resting in the left of the picture above.

Top view

From top to bottom: police lightning system, proximity sensor, ON/OFF switch for electronics power line

SCHEMATICS

CODE /** * Arduino open source project for battery operated electric bike * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #define DISABLE_SPEAKER2 //#define DEBUG #include

#include #include #define PIN_SDCARD A5 #define PIN_SW_GIROFLEX 3 // a #define PIN_SW_REVERSE 4 // b #define PIN_SW_SIREN 5 // c #define PIN_SW_HONK 6 // d #define PIN_SPEAKER 9 // DON'T TOUCH #define PIN_SENSOR_ECHO 10 #define PIN_SENSOR_TRIGGER 11 #define PIN_GIROFLEX 12 #ifdef DEBUG #define DPRINT(x) Serial.print(x) #define DPRINTLN(x) Serial.println(x) #else #define DPRINT(x) #define DPRINTLN(x) #endif TMRpcm audio; // create an object for use in this sketch int giroflex_mode = 0; int last_state = -1; int count_siren = 0; void setup() { pinMode(PIN_SW_GIROFLEX, INPUT_PULLUP); pinMode(PIN_SW_REVERSE, INPUT_PULLUP); pinMode(PIN_SW_SIREN, INPUT_PULLUP); pinMode(PIN_SW_HONK, INPUT_PULLUP); pinMode(PIN_SENSOR_ECHO, INPUT); pinMode(PIN_SENSOR_TRIGGER, OUTPUT); digitalWrite(PIN_SENSOR_TRIGGER, LOW); pinMode(PIN_GIROFLEX, OUTPUT); digitalWrite(PIN_GIROFLEX, LOW); pinMode(PIN_SPEAKER, OUTPUT); pinMode(PIN_SDCARD, OUTPUT); #ifdef DEBUG Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Arduino Micro } #endif

audio.speakerPin = PIN_SPEAKER; audio.setVolume(4); if (!SD.begin(PIN_SDCARD)) { DPRINTLN("SD fail"); tone(PIN_SPEAKER, 392); delay(250); tone(PIN_SPEAKER, 262); delay(500); noTone(PIN_SPEAKER); } else { audio.play("start.wav"); while (audio.isPlaying()); audio.disable(); } DPRINTLN("done setup"); } void loop() { int state = 0; state += debounce(PIN_SW_GIROFLEX) = 50) { return 1; } } while (digitalRead(but) == LOW); return 0; }

void giroflex(int target_mode) { /** MODE 0: OFF MODE 1: LEFT/RIGHT MODE 2: LEFT/RIGHT QUICKLY MODE 3: ALL FLASH MODE 4: BACK/FORTH MODE 5: BACK/FORTH QUICKLY MODE 6: MIXED */ if (giroflex_mode == target_mode) return; DPRINT("giroflex mode "); DPRINTLN(target_mode); /* * audio can mess with timers so we wait for it to finish */ while (audio.isPlaying()); int i; for (i = giroflex_mode; i != target_mode; i = (i + 1) % 7) { digitalWrite(PIN_GIROFLEX, HIGH); delayMicroseconds(900); digitalWrite(PIN_GIROFLEX, LOW); delay(2); digitalWrite(PIN_GIROFLEX, HIGH); delayMicroseconds(2000); digitalWrite(PIN_GIROFLEX, LOW); delay(2); digitalWrite(PIN_GIROFLEX, HIGH); delayMicroseconds(900); digitalWrite(PIN_GIROFLEX, LOW); delay(2); digitalWrite(PIN_GIROFLEX, HIGH); delayMicroseconds(2000); digitalWrite(PIN_GIROFLEX, LOW); delay(2); } giroflex_mode = i; }

165) Arduino Pluto Bluetooth RC Car Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

DFRobot 6 DOF Sensor MPU6050

DC Motor, 12 V

×

1

×

1

L298N Driver Motor

×

2

×

1

×

1

×

1

×

1

×

2

×

1

×

8

Breadboard (generic)

Jumper wires (generic)

Male/Female Jumper Wires

SG90 Micro-servo motor

9V battery (generic) to power the Arduino board

AA Batteries To power the DC motor

Battery Holder, AA x 8 ×

1

NECESSARY TOOLS AND MACHINES 3D Printer (generic)

Hot glue gun (generic)

Soldering Station, 110 V

APPS AND ONLINE SERVICES Arduino IDE

Ultimaker Cura SolidWorks 2019/20 ABOUT THIS PROJECT

Pluto is a project about a particular Bluetooth machine. This car can be controlled by a mobile phone, connecting the car on the Bluetooth we have used the app Arduino Bluetooth Controller which can be found on the Play Store.

On it are installed a self-balancing platform composed of two floors connected to two servo motors, which keep the horizontal plane, by means of an accelerometer, which calculates the angle and sends the same values to the servomotors, but opposite. We decided to do this project for two reasons: 1. have a child play; 2. to be able to bring a glass to a person without emptying it if there are ramps. The operation is simple: sending a Bluetooth signal from the phone the arduino card detects it and makes the machine move left, right, forward, backward or stand still based on what we want it to do to it.

SCHEMATICS

CODE char t; #include //include the required libraries #include //include MPU6050 libraries #include MPU6050 sensor ; //create an instance of the MPU6050 named sensor Servo sg90y; Servo sg90x; int servo_pinX = 2; int servo_pinY = 3;

int motor1A = 4; int motor1B = 5; int motor2A = 6; int motor2B = 7; int16_t ax, ay, az ; int16_t gx, gy, gz ;

//declare 6 16 bit integer variables //declare 6 16 bit integer variables

void setup() { pinMode(servo_pinX, OUTPUT); pinMode(servo_pinY, OUTPUT); pinMode(motor1A, OUTPUT); pinMode(motor1B, OUTPUT); pinMode(motor2A, OUTPUT); pinMode(motor2B, OUTPUT); pinMode(A5, INPUT); pinMode(A4, INPUT); sg90x.attach ( servo_pinX ); sg90y.attach ( servo_pinY ); Wire.begin ( ); //begins the trasmission with MPU6050 sensor.initialize ( ); //initialise the sensor Serial.begin(9600); delay(400); } void forward() { digitalWrite(motor1A, LOW); digitalWrite(motor1B, HIGH); digitalWrite(motor2A, LOW); digitalWrite(motor2B, HIGH); } void reverse() { digitalWrite(motor1A, HIGH); digitalWrite(motor1B, LOW); digitalWrite(motor2B, LOW); digitalWrite(motor2A, HIGH); } void right() { digitalWrite(motor1B, HIGH); digitalWrite(motor1A, LOW); digitalWrite(motor2B, LOW); digitalWrite(motor2A, HIGH); } void left() { digitalWrite(motor1B, LOW); digitalWrite(motor1A, HIGH);

digitalWrite(motor2B, HIGH); digitalWrite(motor2A, LOW); } void nomove() { digitalWrite(motor1B, LOW); digitalWrite(motor1A, LOW); digitalWrite(motor2B, LOW); digitalWrite(motor2A, LOW); } void loop() { sensor.getMotion6 (&ax, &ay, &az, &gx, &gy, &gz); //read 6 values into 6 variables ay = map (ay, -17000, 17000, 0, 180) ; // change the range of the ay value from -17000/17000 to 0/180 sg90y.write (ay); ax = map (ax, -17000, 17000, 0, 180) ; // change the range of the ax value from -17000/17000 to 0/180 sg90x.write (ax); if (Serial.available()) { t = Serial.read(); Serial.println(t); if (t == 'F') { forward(); } else if (t == 'B') { reverse(); } else if (t == 'L') { left(); } else if (t == 'R') { right(); } else if (t == 'S') { nomove(); } } }

//Read the incoming data and store it into variable t

166) Arduino Solar Tracker Projet

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO × 1

SG90 Micro-servo motor

× 2

LDR, 5 Mohm × 4

Resistor 330 ohm × 4

Rotary potentiometer (generic) × 1

Pushbutton Switch, Pushbutton × 2

Mini Solar Panel

× 1

NECESSARY TOOLS AND MACHINES Arduino IDE Parallax PLX-DAQ

ABOUT THIS PROJECT This project presents an open hardware/software test bench for solar tracker. The proposed prototype is based on a dual-axis solar tracker controlled with Arduino Uno which is an open-source prototyping platform based on easy-to-use hardware and software. The solar tracker can be controlled automatically with the help of LightDependent Resistor (LDR) sensors or manually using a potentiometer. Moreover, this test bench provides virtual instrumentation based on Excel in which its solar tracker data can be recorded and presented. The hardware used has been chosen to be inexpensive, compact and versatile. The proposed test bench is designed to help students develop their understanding of control theory and their application. The proposed test bench is presented in Fig. 1. It is based on a solar tracker that can rotate automatically to track the sun with the help of four LDR sensors and two servomotors (SM1 and SM2), or manually using a potentiometer. To switch between the two modes (automatic and manual), a push-button is used. Another push-button is used to link either the SM1(up-down servomotor) or SM2 (left-right servomotor) to the potentiometer to control their movement. Moreover, a computer is used as a virtual instrument to visualize the mode and current, voltage and power of the PV panel according to time in MS Excel. Arduino Uno board is utilized to implement all software requirements of the system.

Fig. 1. Schematic of the proposed test bench Mechanical design As shown in Fig. 2, the computer-aided design (CAD) 3D model of the solar tracker is designed in CATIA. It is composed of the PV panel, the left-right and up-down servomotors, and four LDR sensors. For the horizontal axis, a bearing is fixed in parallel with the up-down servomotor for better flexibility. The solar tracker is designed to have two degrees of freedom, from east to west by the left-right servomotor and from south to north by the up-down servomotor. The LDR sensors are placed in the four corners of the PV panel and are put in dark tubes with a small hole on the top to detect the illumination of the sun. These dark tubes are also considered a concentrator of radiation and are used to increase the solar tracker robustness.

Fig. 2. CAD 3D model of the solar tracker in CATIA Hardware system Fig. 3 presents the electronic circuit of the proposed testbench. For automatic mode, the microcontroller converts the analogs values of LDRsensors (pins A0 to A3) into digitals. Then it controls two servomotors(up-down and left-right) using two Pulse-Width Modulation (PWM) signals (pins 5and 6) to track the sun. The rotation movements occur in two axes, in azimuth from east to west according to the daily sun's path and in elevation from south to north according to the seasonal sun's path. For manual mode, a potentiometer (pin A4) is used to control the movement of the two servo motors, a push-button (pin 11) is deployed

to connect the potentiometer either to up-down servomotor or left-right servomotor. Besides, another pushbutton (pin 12) is used to switch between the two modes. Furthermore, the PV voltage is measured through the analog pin A5 of the Arduino, then the PV current is calculated since the resistor of the load is already known. Next, the PV current, voltage and power versus time and the actual mode are sent to the computer to present them in real-time on MS Excel.

Fig. 3. Electronic circuit of the solar tracker with manual and automatic modes The LDR sensor circuitry is designed as a voltage divider circuit. The variation in the light intensity is proportional to the variation of the divider output voltage. The top of the potential divider is 5 V, the ground is at 0 V, and the output of the voltage divider is connected to an analog input (A0 for instance) of the microcontroller. Subsequently, the Analog to Digital Converter(ADC) of the microcontroller converts the analog value read by A0 into a digital value between 0 and 1023 because the ADC is coded in 10 bits, and according to this value, it is possible to know the

level of light. The value of resistors used in voltage dividers is 330 Ω. Two 180 degrees servomotors are used. A servomotor (MG996R) to control the solar tracker according to the vertical axis, which is the leftright servomotor. And a micro servo motor (SG90) to control the solar tracker according to the horizontal axis, which is the up-down servomotor. The advantage of the servomotor is that we can control its stop, run, the direction of rotation and speed using a single low current wire connected directly to an output of the microcontroller without needing any drivers. The used servo motors are controlled by the Arduino UNO board via 3wire electrical cable as shown in Fig. 3, two wires for supply and one wire for PWM to control its positions. The embedded software design The embedded software is the piece that will be embedded in the hardware (Arduino Uno) to control and monitor the solar tracker test bench. The embedded software is designed to cover the following requirements: 1. The test bench has two modes: manual and automatic. A pushbutton is connected to pin 12 to switch between the two modes. 2. If the manual mode is active, the potentiometer can control servomotors either from east to west for left-right motor or from south to north for the up-down motor. A push-button is connected to pin 11 to switch the potentiometer between the two motors, either it controls the left-right servomotor or up-down servo motor. 3. If the automatic mode is active, the algorithm presented in Fig. 4 will be executed. The latter uses the analog values returned by LDR sensors. For instance, considering azimuth or vertical axis, the average values from two right LDRs and two left LDRs are compared and if the left set of LDRs receives more light, the solar tracker will move in that direction through the left-right servomotor. The latter will continue to rotate until the difference result is in the range [−10, 10]. This range is used to stabilize the controller and once the solar tracker is perpendicular to the sun, no further control is made. On the other hand, if the right set of LDRs receive more light, the solar tracker moves in that direction through the left-right servomotor and will continue to rotate until the difference result is in the

range [−10, 10]. The same way is used for the elevation axis. Moreover, we also determined the average radiation between the four LDR sensors and if this value is less than a little value (8: a value which has been adjusted and tested practically and is returned when the irradiation is null). That is to say, the night has come. In this case, the solar tracker must return to the sun’s rising position. For example, if the sun’s rising position can be reached by setting 0 degrees in the left-right servomotor, and 30 degrees in the up-down servomotor. This can easily be done through the C function “servox. write(angle)” provided by Arduino IDE. 4. The PV voltage acquired through the analog pin A5 must be treated and used to compute the PV current and power. Then all these data and the actual mode must be sent through a USB cable to the computer and then present them in MS Excel.

Fig. 4. The algorithm for automatic mode of the solar tracker The PLX-DAQ Excel Macro is used for data acquisition from the Arduino microcontroller to an Excel Spreadsheet. We only need to download it. After installation, a folder named "PLX-DAQ" will automatically be created on the PC in which a shortcut named "PLX-DAQ Spreadsheet" is inside. Then, to establish the communication between the board and Excel, we just need to open the Spreadsheet and defining the connections settings (Baud rate and port) in the PLX-DAQ window (Fig. 5). Thereafter, after clicking on "connect" the output data will be collected and displayed in real-time on the Excel Spreadsheet

Fig. 5. PLX-DAQ Spreadsheet window The prototype Figure 6 shows the solar tracker in detached and assembled states. As presented, the entire structure has been manufactured using wooden plates, and it is clear that the all mentioned components have been used to build the solar tracker with manual and automatic modes (LDR sensors, Arduino Uno, Servo motors, potentiometer, pushbuttons, and the small PV panel).

Fig. 6. Composition of the solar tracker Figure 7 shows the entire test bench, solar tracker with virtual instrumentation, and an artificial lamp that can expose light to test the solar tracker. The solar tracker and the computer are connected through a USB cable. Once the PV voltage is acquired, the controller treats this information and uses it to compute the PV current and power. Then, all these data are sent to the computer to present them in MSExcel. From Figs. 5 and 6, it is clear that the proposed test bench is small, flexible and easy to use. It can enable students, researchers and engineers to apply their algorithms in an easy way before proceeding with the implementation of a large solar tracking device.

Fig. 7. The entire test bench with virtual instrumentation SCHEMATICS

CODE //Servo motor library #include //Initialize variables int mode = 0; int axe = 0; int buttonState1 = 0; int buttonState2 = 0; int prevButtonState1 = 0; int prevButtonState2 = 0; int ldrtopr= 0; int ldrtopl = 1; int ldrbotr = 2; int ldrbotl = 3; int topl = 0; int topr = 0; int botl = 0;

// top-right LDR // top-left LDR // bottom-right LDR // bottom-left LDR

int botr = 0; //Declare two servos Servo servo_updown; Servo servo_rightleft; int threshold_value=10;

//measurement sensitivity

void setup() { Serial.begin(9600); //serial connection setup //opens serial port, sets data rate to 9600 bps Serial.println("CLEARDATA"); //clear all data that’s been place in already Serial.println("LABEL,t,voltage,current,power,Mode"); //define the column headings (PLX-DAQ command) pinMode(12, INPUT); pinMode(11, INPUT); pinMode(A4, INPUT); movement

//Mode switch Button //Axis switch //Potentiometer for right-left movement and for up-down

servo_updown.attach(5); servo_rightleft.attach(6); }

//Servo motor up-down movement //Servo motor right-left movement

void loop() { // pv_power(); char Mode; float volt = analogRead(A5)*5.0/1023; float voltage = 2*volt; // Volt=(R1/R1+R2)*Voltage / R1=R2=10Ohms => voltage=2*volt) float current = voltage/20; // I=voltage/(R1+R2) float power = voltage*current; Serial.print("DATA,TIME,"); // PLX-DAQ command Serial.print(voltage); //send the voltage to serial port Serial.print(","); Serial.print(current); //send the current to serial port Serial.print(","); Serial.print(power); //send the power to serial port Serial.print(","); // Serial.println(Mode); buttonState1 = digitalRead(12); if (buttonState1 != prevButtonState1) { if (buttonState1 == HIGH) {

//Change mode and ligh up the correct indicator if (mode == 1) { mode = 0; } else { mode = 1; } } } prevButtonState1 = buttonState1; delay(50); // Wait for 50 millisecond(s) if (mode == 0) { Mode='M'; Serial.println(Mode); //send Mode "Manual" to serial port manualsolartracker(); } else { // mode automatic Mode = 'A'; Serial.println(Mode); automaticsolartracker(); //send Mode "Automatic" to serial port } } void automaticsolartracker(){ //capturing analog values of each LDR topr= analogRead(ldrtopr); //capturing analog value of top right LDR topl= analogRead(ldrtopl); //capturing analog value of top left LDR botr= analogRead(ldrbotr); //capturing analog value of bot right LDR botl= analogRead(ldrbotl); //capturing analog value of bot left LDR // calculating average int avgtop = (topr + topl) / 2; int avgbot = (botr + botl) / 2; int avgleft = (topl + botl) / 2; int avgright = (topr + botr) / 2; //Get the different int diffelev = avgtop - avgbot; bot int diffazi = avgright - avgleft; left

//average of top LDRs //average of bottom LDRs //average of left LDRs //average of right LDRs

//Get the different average betwen LDRs top and LDRs //Get the different average betwen LDRs right and LDRs

//left-right movement of solar tracker if (abs(diffazi) >= threshold_value){ then the threshold_value

//Change position only if light difference is bigger

if (diffazi > 0) { if (servo_rightleft.read() < 180) { servo_rightleft.write((servo_updown.read() + 2)); } } if (diffazi < 0) { if (servo_rightleft.read() > 0) { servo_rightleft.write((servo_updown.read() - 2)); } } } //up-down movement of solar tracker if (abs(diffelev) >= threshold_value){ //Change position only if light difference is bigger then thethreshold_value if (diffelev > 0) { if (servo_updown.read() < 180) { servo_updown.write((servo_rightleft.read() - 2)); } } if (diffelev < 0) { if (servo_updown.read() > 0) { servo_updown.write((servo_rightleft.read() + 2)); } } } } void manualsolartracker(){ buttonState2 = digitalRead(13); if (buttonState2 != prevButtonState2) { if (buttonState2 == HIGH) { //Change mode and ligh up the correct indicator if (axe == 1) { axe = 0; } else { axe = 1; } } } prevButtonState2 = buttonState2; delay(50); // Wait for 50 millisecond(s) if (axe == 0) { //control right-left movement servo_rightleft.write(map(analogRead(A4), 0, 1023, 0, 180)); } else { // //control up-down movement

servo_updown.write(map(analogRead(A4), 0, 1023, 0, 180)); } }

167) Arduino To The Minute Word Clock Projet

COMPONENTS AND SUPPLIES Arduino Nano R3 ×

1

×

1

Real Time Clock (RTC)

Jumper wires (generic)

0.91 Inch 128x32 IIC I2C Blue OLED LCD Display DIY Oled Module SSD1306 Driver IC DC 3.3V 5V For Arduino PIC

×

1

×

1

ABOUT THIS PROJECT This project, another clock, gives all the information you need with up to the minute time in words on a 128 X 32 OLED display. Small, compact, easy to wire, long code but fun. Used legos to build a little enclosure.

SCHEMATICS

CODE // Date and time functions using a DS1307 RTC connected via I2C and Wire lib #include #include "RTClib.h" #include #include #include #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_RESET); #if (SSD1306_LCDHEIGHT != 32) #error("Height incorrect, please fix Adafruit_SSD1306.h!"); #endif #define Today RTC_DS1307 rtc; char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday",

"Thursday", "Friday", "Saturday"}; void setup () { while (!Serial); // for Leonardo/Micro/Zero Serial.begin(9600);

if (! rtc.begin()) { while (1); } if (! rtc.isrunning()) { // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // This line sets the RTC with an explicit date & time, for example to set // January 21, 2014 at 3am you would call: // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); } Wire.begin(); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32) // init done //Clear the buffer. display.clearDisplay(); text(); } void text(void) { display.setTextSize(1); display.setTextColor(WHITE); } void Display () { display.clearDisplay(); DateTime now = rtc.now(); //set day of week display.setCursor(0,0); display.print("Today is "); display.print(daysOfTheWeek[now.dayOfTheWeek()]);

//set date display.setCursor(0,12);

int mo=now.month(); if ((mo>0)&&(mo1)&&(mo2)&&(mo3)&&(mo4)&&(mo5)&&(mo6)&&(mo7)&&(mo8)&&(mo9)&&(mo10)&&(mo11)&&(mo12){ hr=hr-12; } if ((hr>0)&&(hr1)&&(hr2)&&(hr3)&&(hr4)&&(hr5)&&(hr6)&&(hr7)&&(hr8)&&(hr9)&&(hr10)&&(hr11)&&(hr0)&&(m1)&&(m2)&&(m3)&&(m4)&&(m5)&&(m6)&&(m7)&&(m8)&&(m9)&&(m10)&&(m11)&&(m12)&&(m13)&&(m14)&&(m15)&&(m16)&&(m17)&&(m18)&&(m19)&&(m20)&&(m21)&&(m22)&&(m23)&&(m24)&&(m25)&&(m26)&&(m27)&&(m28)&&(m29)&&(m30)&&(m31)&&(m32)&&(m33)&&(m34)&&(m35)&&(m36)&&(m37)&&(m38)&&(m39)&&(m40)&&(m41)&&(m42)&&(m43)&&(m44)&&(m45)&&(m46)&&(m47)&&(m48)&&(m49)&&(m50)&&(m51)&&(m52)&&(m53)&&(m54)&&(m55)&&(m56)&&(m57)&&(m58)){ display.print("Fifty-Nine"); } if (m= BUF_SIZE-3)) // end of message character or full buffer { // put in a message separator and end the string

newMessage[putIndex++] = ' '; newMessage[putIndex] = '\0'; // restart the index for next filling spree and flag we have a message waiting putIndex = 0; newMessageAvailable = true; } else if (newMessage[putIndex] != '\r') // Just save the next char in next location putIndex++; } } void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col) // Callback function for data that is being scrolled off the display { #if PRINT_CALLBACK Serial.print("\n cb "); Serial.print(dev); Serial.print(' '); Serial.print(t); Serial.print(' '); Serial.println(col); #endif } uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t) // Callback function for data that is required for scrolling into the display { static char *p = curMessage; static uint8_t state = 0; static uint8_t curLen, showLen; static uint8_t cBuf[8]; uint8_t colData; // finite state machine to control what we do on the callback switch(state) { case 0: // Load the next character from the font table showLen = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf); curLen = 0; state++; // if we reached end of message, reset the message pointer if (*p == '\0') { p = curMessage; // reset the pointer to start of message

if (newMessageAvailable) // there is a new message waiting { strcpy(curMessage, newMessage); // copy it in newMessageAvailable = false; } } // !! deliberately fall through to next state to start displaying case 1: // display the next part of the character colData = cBuf[curLen++]; if (curLen == showLen) { showLen = CHAR_SPACING; curLen = 0; state = 2; } break; case 2: // display inter-character spacing (blank column) colData = 0; curLen++; if (curLen == showLen) state = 0; break; default: state = 0; } return(colData); } void scrollText(void) { static uint32_t prevTime = 0; // Is it time to scroll the text? if (millis()-prevTime >= scrollDelay) { mx.transform(MD_MAX72XX::TSL); // scroll along - the callback will load all the data prevTime = millis(); // starting point for next time } } void printText(uint8_t modStart, uint8_t modEnd, char *pMsg) // Print the text string to the LED matrix modules specified.

// Message area is padded with blank columns after printing. { uint8_t state = 0; uint8_t curLen; uint16_t showLen; uint8_t cBuf[8]; int16_t col = ((modEnd + 1) * COL_SIZE) - 1; mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF); do // finite state machine to print the characters in the space available { switch(state) { case 0: // Load the next character from the font table // if we reached end of message, reset the message pointer if (*pMsg == '\0') { showLen = col - (modEnd * COL_SIZE); // padding characters state = 2; break; } // retrieve the next character form the font file showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf); curLen = 0; state++; // !! deliberately fall through to next state to start displaying case 1: // display the next part of the character mx.setColumn(col--, cBuf[curLen++]); // done with font character, now display the space between chars if (curLen == showLen) { showLen = CHAR_SPACING; state = 2; } break; case 2: // initialize state for displaying empty columns curLen = 0; state++; // fall through case 3: // display inter-character spacing or end of message padding (blank columns)

mx.setColumn(col--, 0); curLen++; if (curLen == showLen) state = 0; break; default: col = -1; // this definitely ends the do loop } } while (col >= (modStart * COL_SIZE)); mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON); }

void setup() { mx.begin(); mx.setShiftDataInCallback(scrollDataSource); mx.setShiftDataOutCallback(scrollDataSink); scrollDelay = SCROLL_DELAY; strcpy(curMessage, "AV Rocks! newMessage[0] = '\0';

");

Serial.begin(57600); Serial.print("\n[MD_MAX72XX Message Display]\nType a message for the scrolling display\nEnd message line with a newline"); } void loop() { scrollYes = digitalRead(scrollSwitch); readSerial(); if (scrollYes == 0){ printText(0, MAX_DEVICES-1, newMessage); } else { scrollText(); } }

182) Arduino Magic Projector

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO ×

1

×

1

9V battery (generic)

AA Batteries

×

1

×

1

×

1

×

8

×

1

×

1

×

1

×

1

Led matrix 8x8 common cathode I did use the GMM-23088CSB, but every generic matrix should work, just need to ensure what's the pinout diagram. Breadboard (generic)

Resistor 330 ohm

9V Battery Clip

General Purpose Transistor NPN

Switch Hand lamp You can use any source of light

that produces a directed beam of light. I did use a led hand lamp: NF-A651. Resistor 2.7K ohm

×

1

×

1

×

1

×

1

×

1

Jumper wires (generic) Any wire should work

Cardboard box Recycled carton ?? Glue Matt black paper

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

Hot glue gun (generic)

Cutting pliers

APPS AND ONLINE SERVICES Arduino IDE

Led matrix sprite generator ABOUT THIS PROJECT Most of the time, engineers seem to be non-creative people. But that's not true! We are much more creative than people think. Recently I had to find an original way to ask a girl to be my girlfriend, so after a little brainstorm, I decided to use some components that I've found in my desk to make the date very special for her. Step One: Matrix Control Display things on the matrix can be done by two ways: using a led driver MAX7219, which reduce the amount of pins used by the Arduino and reduce the number of resistors in the circuit. Or connecting pin by pin on the matrix to the Arduino, this makes the circuit too big and uncomfortable to work with, and you end with 2 pins left to use on any other thing. My first try was to use the MAX7219, but due to noisy signals I give up and switch to the hard method. This problem can be solved using short connections as the datasheet said on page 10.

MAX7219 datasheet wiring recommendations

So, for the next try, I wire every pin on the matrix to each one of the pins on the Arduino.

Full circuit diagram Remember to use current limiting resistors on each cathode, I decided to use 330 Ohm. Code for the Matrix The program can be found on my GitHub repo. It's well commented, so I won't get deep on it. But if you do the wiring as I did, everything should work. To generate every image on the matrix, I found a useful resource on the internet, just need to set the dots to on or off, copy the resulting code and delete the first two comma separated values of the array.

Delete the red underlined values, and change the name if you want Step two: Controlling the light This was a tricky part because the lamp I did use was borrowed from a friend and he asked me not to do anything irreversible to his lamp. So for the connections, instead of do some soldering, I had to find a way to attach the cables to the battery and the lamp using just cardboard and tape. At the beginning, I want to use a light bulb, so that's the reason why I have a relay on the circuit. But when I do the first try with it, I realized that the light bulb don't work for this task because the light beam it's not focused. So I replace it with the LED lamp, but I have not time to make the circuit again, so the relay stay in place. It should work only using the transistor.

Breadboard with light control circuit

Lamp attached to the cardboard using wires, the two of the back are the power cables I have two batteries on my circuit because I don't have wires of the long needed to connect the light control circuit and the matrix control circuit,

but it should work using only one 9V battery to power all the circuit. Step Three: Box Enclosure The magic box has two compartments. The first is where the Arduino and the matrix are attached. The second have the light and his control circuit in it. In order for the projection to work, you have to be careful when get the hardware inside the box, anything should be in front of the light. I've tried to attach the wires very well to avoid any problem. The box should look like this, but feel free to make your own design.

Front

Side

Bottom view -I'm sorry for the mess Control panel For the control panel I get some translucent black fabric and cover the

matrix with it. When it's turn off, the led behind are barely visible, so it gives a nice effect to the box. I cover all the cardboard with matte black paper to make it looking good, and finally print text that was made in Canva on acetate paper and put it on one side of the box. Image below:

Projection sheet

SCHEMATICS

CODE /******************/ // Control an 8x8 led matrix(GMM-23088CSB) with an Arduino UNO // Pin connections: // Remember use a resistor on each anode. // Columns // matrix | 13 | 3 | 4 | 10 | 6 | 11 | 15 | 16 | // Arduino | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // // Raws // matrix | 9 | 14 | 8 | 12 | 1 | 7 | 2 | 5 | // Arduino | 10 | 11 | 12 | 13 | A0 | A1 | A2 | A3 | /******************/

byte sp[]= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; byte c_1[] = {B00000000,B01111110,B01000010,B01000010,B01000010,B01000010,B01111110,B00000000 byte c_2[] = {B00000000,B00000000,B00111100,B00100100,B00100100,B00111100,B00000000,B00000000 byte c_3[] = {B00000000,B00000000,B00000000,B00011000,B00011000,B00000000,B00000000,B00000000 byte jenny[] = {B00000000,B01111100,B00010000,B00010000,B00010000,B00010000,B01110000,B00000000 byte flecha_1[] = {B00000000,B00001000,B00001100,B01111110,B00001100,B00001000,B00000000,B00000000 byte flecha_2[] = {B00000000,B00001000,B00001100,B01111110,B01111110,B00001100,B00001000,B00000000 byte heart[] = {B00000000,B01101100,B11111110,B11111110,B01111100,B00111000,B00010000,B00000000 byte heart_outline[] = {B00000000,B01101100,B10010010,B10000010,B01000100,B00101000,B00010000,B00000000 byte load1[] = {B00000000,B00000000,B00000000,B00000000,B00000000,B11111110,B10000010,B11111110 byte load2[] = {B00000000,B00000000,B00000000,B00000000,B00000000,B11111110,B11000010,B11111110 byte load3[] = {B00000000,B00000000,B00000000,B00000000,B00000000,B11111110,B11100010,B11111110 byte load4[] = {B00000000,B00000000,B00000000,B00000000,B00000000,B11111110,B11110010,B11111110 byte load5[] = {B00000000,B00000000,B00000000,B00000000,B00000000,B11111110,B11111010,B11111110

byte load6[] = {B00000000,B00000000,B00000000,B00000000,B00000000,B11111110,B11111110,B11111110 //byte load7[] = {B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111,B11111111 byte Selecciona( char c, byte fil) { if (c == '1') return(c_1[fil]); if (c == '2') return(c_2[fil]); if (c == '3') return(c_3[fil]); if (c == '4') return(jenny[fil]); if (c == '5') return(heart[fil]); if (c == '6') return(flecha_1[fil]); if (c == '7') return(flecha_2[fil]); if( c == 'l' ) return (load1[fil]); if( c == 'o' ) return (load2[fil]); if( c == 'a' ) return (load3[fil]); if( c == 'd' ) return (load4[fil]); if( c == 'i' ) return (load5[fil]); if( c == 'n' ) return (load6[fil]); //if( c == 'g' ) return (load7[fil]); if (c == ' ') return( sp[fil]); } void setup() { for (int j=2; j> pos ; // Shift bits b=b&1; // coger solo el ultimo bit return b ; } void Clear() { for (int j=2; j= MAXPULSE) && (currentpulse != 0)) { printpulses(); currentpulse=0; return; } } pulses[currentpulse][1] = lowpulse; // we read one high-low pulse successfully, continue! currentpulse++; } void printpulses(void) { Serial.println("\n\r\n\rReceived: \n\rOFF \tON"); for (uint8_t i = 0; i < currentpulse; i++) { Serial.print("delayMicroseconds("); Serial.print(pulses[i][0] * RESOLUTION, DEC); Serial.print("); pulseIR("); Serial.print(pulses[i][1] * RESOLUTION, DEC); Serial.println(");"); } }

code 2Arduino use secondly for transmitting ir.

int IRledPin = 3; void setup() { pinMode(IRledPin, OUTPUT); Serial.begin(9600); }

void loop() { int a; if(Serial.available()>0) { a=Serial.read(); switch(a) { case 1: power(); //if it receives the number "1" from the app then the case one will be executed break; case 2:tvpower(); break; case 3:chplus(); break; case 4:chminus(); break; case 5:volplus(); break; case 6:volminus(); break; //all the data provided corresponds to my tv remote thus you have to modify to your needs case 10: zero(); //if it receives the number "10" from the app then the case 10 will be executed thus the respective channel is switched delay(700); nine(); delay(700); one(); delay(700); zero(); delay(700); break; //channel number 910 will be switched } } void pulseIR(long microsecs) { cli(); while (microsecs > 0) { digitalWrite(IRledPin, HIGH); delayMicroseconds(10); digitalWrite(IRledPin, LOW);

delayMicroseconds(10); microsecs -= 26; } sei(); } void power() /*the function stores the data for the power button taken from the step-1*/ { //the data is for my remote so update the data with yours delayMicroseconds(57608 ); pulseIR( 2680 ); delayMicroseconds(980 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(960 ); pulseIR( 400 ); delayMicroseconds(980 ); pulseIR( 860 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 );

pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 860 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(960 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(61644 ); pulseIR( 2700 ); delayMicroseconds(980 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(980 ); pulseIR( 400 ); delayMicroseconds(960 ); pulseIR( 880 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 );

pulseIR( 420 ); delayMicroseconds(480 ); pulseIR( 420 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 400 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(500 ); pulseIR( 860 ); delayMicroseconds(520 ); pulseIR( 400 ); delayMicroseconds(960 ); pulseIR( 420 ); delayMicroseconds(500 ); pulseIR( 400 );

} void chplus() { //put the data of your channel plus button in this section } void ch minus() { } void one() { } void two() { } void three() { } //add for all the 10 numbers. //similarly you can add any no of functions for each buttons

188) Arduino LCD Stopwatch with Split Time

COMPONENTS AND SUPPLIES Breadboard (generic)

×

1

×

1

Alphanumeric LCD, 16 x 2

Jumper wires (generic)

×

1

×

4

×

1

×

1

Tactile Switch, Top Actuated

Arduino UNO & Genuino UNO

Rotary potentiometer (generic)

ABOUT THIS PROJECT I wanted to create a simple stopwatch with a lcd, and wich could store 4 split time in memory. How does it work: This stopwatch has 4 buttons, in the schematic, from right to left: Start, Pause, Split (Partial time), and Scroll the split time. Once you press the start button for the first time, the chronometer starts. If you press the pause button it will stop, very simple. If while

it's running, you press the third button (Split), it will save that time in memory (in Old: ), and it will start a new split. When the clock is in pause mode, if you press the 4th button (scroll), you'll enter in the function to see the last 4 split time. Once you press start again, the chronometer just will start again. The code is explained in the comments SCHEMATICS

CODE #include //PIN 5 R/W to Ground, for writing

//LCD Mode : 4 data pin //Functions: Start, stop, saving up to 4 partial time in memory. //10 millis = 1 hundredth of a second. The chronometer measures hour, minutes, seconds, and hundredths of a second. //Buttons with internal Pullup, so if they get pressed we get LOW const int start = 8; //Start the stopwatch const int pausa = 9; //Pausa const int partial = 10; //Save a partial const int scroll_partial = 11; //If paused, check the 4 last saved partial int x = 0; //Variable to manage the loop //LCD int lcdclear = 0; //this to variables are needed for managing int Display = 0; //the display, to clear and print //chronometer int cents = 0; int seconds = 0; int minutes = 0; int hours = 0; const int interval = 10; //Every 10 milliseconds i increase 1 cent unsigned long previousMillis = 0; int c1, c2, s1, s2, m1, m2, h; //Variables used to put in the form //h:m2m1:s2s1:c2c1 //Partial: I save 4 partial, that can be seen if stopwatch is stopped int partial2[7]; //penultimate partial (The one that stays in Old). The last partial stays in New: int partial3[7]; int partial4[7]; int scrolling = 0; //Used to scroll the saved partial times

LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // RS-Enable-D4-D5-D6-D7 in that digitalPin void setup() { pinMode(start, INPUT_PULLUP); //In the schematic from right to left pinMode(pausa, INPUT_PULLUP);//there are start-pausa-partial-scroll_partial pinMode(partial, INPUT_PULLUP); pinMode(scroll_partial, INPUT_PULLUP); lcd.begin(16,2); lcd.print("Press start"); }

void loop() { if (x == 0) { //Initially is 0 while(digitalRead(start) == HIGH) {}; //Until i press the button, the chronometer doesn't start x++; //When i press the button, i go out from this cycle, x++ and i cannot return here anymore } if (lcdclear == 0){ //Condition to clear the display, used in the various functions lcd.clear(); lcdclear++; } if (Display == 0){ //Also this is used to clear display lcd.home(); lcd.print("Now: "); //With this condition, i can print "Now: " one single time, otherwise the chronometer wouldn't be precise Display++; scrolling = 0; //When i exit from the partial menu, then if i go in the partial menu again i always get in PAR1 and PAR2 } chronometer(); //At the end of every increase, i control if stop is pressed. And also if the partial function is pressed pause(); f_partial(); } void chronometer(void){ //This function print: "New: Actual time" unsigned long currentMillis = millis(); //If for the updating. If it is true, it means 1 cent of a second had passed. Update cents, minutes, seconds, hours and then i write on the lcd if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; cents++; if (cents == 100){ cents = 0; seconds++; if (seconds == 60) { seconds = 0; minutes++; if (minutes == 60){ minutes = 0; hours++; if (hours == 24) hours = 0; } } } int cent = cents;

int sec = seconds; int minu = minutes; //Taking the digits separeted h = hours; //For the other funcionts, so i can put hours = 0 and h still is the last value c1 = cent%10; cent /= 10; c2 = cent%10; s1 = sec%10; sec /= 10; s2 = sec%10; m1 = minu%10; minu /= 10; m2 = minu%10; lcd.setCursor(6, 0); lcd.print(h); lcd.print(':'); lcd.print(m2); lcd.print(m1); lcd.print(':'); lcd.print(s2); lcd.print(s1); lcd.print(':'); lcd.print(c2); lcd.print(c1); } } void scrollPartial(void){ while(digitalRead(scroll_partial) == LOW) {}; //Debounce, as long as i press the button the real function doesn't start if (scrolling == 0) { //Visualize the last 2 partials lcd.clear(); lcd.home(); lcd.print("PAR1:"); lcd.setCursor(6, 0); lcd.print(h); lcd.print(':'); lcd.print(m2); lcd.print(m1); lcd.print(':'); lcd.print(s2); lcd.print(s1); lcd.print(':'); lcd.print(c2); lcd.print(c1); lcd.setCursor(0, 1); lcd.print("PAR2:");

lcd.setCursor(6, 1); lcd.print(partial2[0]); lcd.print(':'); lcd.print(partial2[1]); lcd.print(partial2[2]); lcd.print(':'); lcd.print(partial2[3]); lcd.print(partial2[4]); lcd.print(':'); lcd.print(partial2[5]); lcd.print(partial2[6]); Display = 0; //When i press start the display must be cleared lcdclear = 0; //When i press start the display must be cleared cents = seconds = minutes = hours = 0; scrolling++; } else if (scrolling == 1){ //Visualize 3th and 4th partial lcd.clear(); lcd.home(); lcd.print("PAR3:"); lcd.setCursor(6, 0); lcd.print(partial3[0]); lcd.print(':'); lcd.print(partial3[1]); lcd.print(partial3[2]); lcd.print(':'); lcd.print(partial3[3]); lcd.print(partial3[4]); lcd.print(':'); lcd.print(partial3[5]); lcd.print(partial3[6]); lcd.setCursor(0, 1); lcd.print("PAR4:"); lcd.setCursor(6, 1); lcd.print(partial4[0]); lcd.print(':'); lcd.print(partial4[1]); lcd.print(partial4[2]); lcd.print(':'); lcd.print(partial4[3]); lcd.print(partial4[4]); lcd.print(':'); lcd.print(partial4[5]); lcd.print(partial4[6]); Display = 0; //When i press start the display must be cleared lcdclear = 0; //When i press start the display must be cleared

cents = seconds = minutes = hours = 0; scrolling = 0; } }

void pause(void){ //If pause is pressed, i stop in this function until start doesn't get pressed again if (digitalRead(pausa) == HIGH) return; else if (digitalRead(pausa) == LOW){ //Stuck in this cycle until i press start while(digitalRead(start) == HIGH) { if (digitalRead(scroll_partial) == LOW) //If i press the button for seeing the partial, i enter in that function scrollPartial(); //When scrollPartial() ends, i'm still in this function, so if i press start the chronometer starts back normal } } } void f_partial(void){ //If this button is pressed, i put the current value of New in Old, and a new crhonometer starts if (digitalRead(partial) == HIGH) return; else if (digitalRead(partial) == LOW ){ lcd.clear(); lcd.setCursor(0, 1); //The values calculated in the function chronometer can be used, h,m,s,c lcd.print("Old: "); lcd.setCursor(6, 1); lcd.print(h); lcd.print(':'); lcd.print(m2); lcd.print(m1); lcd.print(':'); lcd.print(s2); lcd.print(s1); lcd.print(':'); lcd.print(c2); lcd.print(c1); //When i come here, i've got the old values for h,m,s,c, i save it in the partial array Display = 0; //The new is written again cents = 0; seconds = 0;

minutes = 0; hours = 0; partial4[0] = partial3[0]; //Partial4[] is updated with the old partial3[] partial4[1] = partial3[1]; partial4[2] = partial3[2]; partial4[3] = partial3[3]; partial4[4] = partial3[4]; partial4[5] = partial3[5]; partial4[6] = partial3[6];

partial3[0] = partial2[0]; //Partial3[] is updated with the old partial2[] partial3[1] = partial2[1]; partial3[2] = partial2[2]; partial3[3] = partial2[3]; partial3[4] = partial2[4]; partial3[5] = partial2[5]; partial3[6] = partial2[6]; partial2[0] = h; //Update partial2 with OLD partial2[1] = m2; partial2[2] = m1; partial2[3] = s2; partial2[4] = s1; partial2[5] = c2; partial2[6] = c1; while(digitalRead(partial) == LOW) {}; //Debounce, until i press the button i stay here } }

189) Arduino Mains Failure Detector

COMPONENTS AND SUPPLIES Arduino Nano R3 Arduino NANO or UNO or PRO MINI ×

1

×

1

×

1

GPRS shield SIM900

12V switching wall power supply

SparkFun Solder-able Breadboard - Mini

×

1

×

3

×

2

×

2

×

1

×

1

×

2

×

1

×

2

Female Header 8 Position 1 Row (0.1") One with short pins, two with long pins to stack on GPRS shield

Male power Jack

Female power jack

9V battery (generic)

9V Battery Clip

Resistor 10k ohm

Resistor 5,6K ohm or 6,8k ohm

1N4007 – High Voltage, High Current Rated Diode

Capacitor 100 µF ×

1

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

ABOUT THIS PROJECT It's very easy: if mains power fails, the GPRS module sends an alarm message with an SMS to my cell-phone. Pin D2 of the Arduino is normally at HIGH level (see below: 4, 6V from the resistor divider R2/R1+R3). When mains power fails, it goes at LOW level and the GPRS module sends a message. When the electric power returns, the GPRS module sends an "ok" message. I used a solderable breadboard to build the circuit and headers & jumpers to connect the GPRS shield as indicated: Connector 1 from Arduino D7 to GPRS TXD (UART) Connector 2 from Arduino D8 to GPRS RXD (UART) Connector 3 from Arduino D9 to GPRS D9 (board) Arduino GND to GPRS GND (UART)

Schematics The 9V battery feeds Arduino and GPRS shield when electricity supply, normally given through the 12V jack, is off.

Testing the system with Arduino NANO I tested it and works well with UNO, NANO and MINI with the same software.

SCHEMATICS

CODE /* GPRS Shield with SIM900 Connections: Arduino UNO pin 2 to Vin Arduino UNO pin 7 to Shield TXD Arduino UNO pin 8 to Shield RXD Arduino UNO pin 9 to Shield pin 9 (shield ON/OFF) Arduino UNO GND to Shield GND */ #include // Configure software serial port SoftwareSerial SIM900(7, 8);

//Variable to save incoming SMS characters char incoming_char=0; //Allarm status byte allarmSent = LOW; void setup() { // Switch on the GSM shild pinMode(9,OUTPUT); digitalWrite(9, HIGH); delay(2000); digitalWrite(9, LOW); delay(5000); // Set pin 2 as input for Vin detection pinMode(2,INPUT); // Arduino communicates with SIM900 GSM shield at a baud rate of 19200 SIM900.begin(19200); // Give time to GSM shield to log on to network delay(30000); // AT command to set SIM900 to SMS mode SIM900.print("AT+CMGF=1\r"); delay(100); sendSMSready(); // Set module to send SMS data to serial out upon receipt // SIM900.print("AT+CNMI=2,2,0,0,0\r"); // delay(100); } void loop() { // Display any text that the GSM shield sends out on the serial monitor if(SIM900.available() >0) { //Get the character from the cellular serial port incoming_char=SIM900.read(); //Print the incoming character to the terminal Serial.print(incoming_char); } while (digitalRead(2) == HIGH) {} if(digitalRead(2) == LOW && allarmSent == LOW) { // whait 1" more and send message if pin 2 is already LOW delay(1000); if(digitalRead(2) == LOW) sendSMSallarm(); } while (digitalRead(2) == LOW) {} if(digitalRead(2) == HIGH && allarmSent == HIGH) sendSMSallarmOFF(); }

void sendSMSallarm() { // Set recipient's mobile number in international format SIM900.println("AT + CMGS = \"+XXXXXXXXXXXX\""); delay(100); // Set SMS message SIM900.println("*** MANCANZA TENSIONE RETE ***"); delay(100); // End AT command with a ^Z, ASCII code 26 SIM900.println((char)26); delay(100); SIM900.println(); // Give module time to send SMS delay(5000); allarmSent = HIGH; } void sendSMSallarmOFF() { // Set recipient's mobile number in international format SIM900.println("AT + CMGS = \"+XXXXXXXXXXXX\""); delay(100); // Set SMS message SIM900.println("*** TENSIONE RETE OK ***"); delay(100); // End AT command with a ^Z, ASCII code 26 SIM900.println((char)26); delay(100); SIM900.println(); // Give module time to send SMS delay(5000); allarmSent = LOW; } void sendSMSready() { // Set recipient's mobile number in international format SIM900.println("AT + CMGS = \"+XXXXXXXXXXXX\""); delay(100); // Set SMS message SIM900.println("*** SISTEMA CONNESSO ***"); delay(100); // End AT command with a ^Z, ASCII code 26 SIM900.println((char)26); delay(100); SIM900.println();

// Give module time to send SMS delay(5000); }

190) Arduino Using Median Filter To Display DHT22 and RTC

COMPONENTS AND SUPPLIES DHT22 Temperature Sensor ×

1

Robojax DS3231 IIC Precision Real time Clock Module Any equivalent DS3231 IIC RTC should work Kuman 0.96 Inch Yellow Blue IIC OLED Module I2c Any equivalent 0.96 inch OLED should work

×

1

×

1

Arduino Nano R3

ABOUT THIS PROJECT This project uses a median filter to smooth and de-spike data from a DHT22 Temperature and Humidity Sensor. It also uses a DS3231 Realtime Clock Module (AT24C32) to display the date/time on a 0.96 inch Yellow/Blue IIC OLED I2c 128x64 display. All the hardware fits on a single breadboard and is powered by the USB interface or alternately by an external power supply (typically a wall wart driving a breadboard power supply module.) I chose a median filter to remove any jitter from the DHT22. This may not necessary for most applications as the DHT22 is quite stable, but this filter is simple and removes any spikes. Experience has shown that it removes almost all noise with very little impact on sensor response time. The width of the filter affects this and can be adjusted in the sketch. The filter width must be an odd number, and 5 or 7 seem to work well. The wider the filter, the more effective it is at removing

spikes. The downside is a wide filter will decrease response time. The RTC is the standard DS3231. You have to initially set the time and date with the SetTime sketch in the DS1307RTC library. You can find that library here: https://github.com/PaulStoffregen/DS1307RTC If you install the optional CR2032 battery in the Clock Module this should hold the time for several years, so this is a one-time procedure. The exception is if you wish to use DST, you'll have to run the SetTime sketch each spring and fall. I am using the U8glib library to drive the OLED display. You can obtain a copy here: https://github.com/olikraus/u8glib

SCHEMATICS

CODE /* Use an Arduino Nano to display temp/humidy on 0.96 inch Yellow/Blue IIC OLED I2c serial 128x64 Display Use an Adafruit DHT22 Temperature and Humidity Sensor (accuracy ±2%) These data might bounce around somewhat because the sensor can be a little noisy at times. We use a simple median filter to smooth out the noise Arduino Nano OLED = pin A4 to SDA and pin A5 to SLC

*/

// This library allows you to communicate with I2C devices, in this // case the RTC and OLED display #include // For the DS3231 Real time Clock Module (AT24C32 Module) #include // Include DHT Library from Adafruit #include "DHT.h"; /* DHT22 pin-out: Pin 1 VCC Pin 2 Data out Pin 3 Not connected Pin 4 Ground */ #include "U8glib.h" // For the OLED - Obtain from: https://github.com/olikraus/u8glib // Define Constants #define dhtPin 7 // DHT-22 Output Pin connection #define dhtType DHT22 // DHT Type is a DHT 22 (AM2302) // Initialize OLED U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // Initialize DHT sensor

DHT dht(dhtPin, dhtType); tmElements_t tm; // For the RTC #define buff_size 7 // Must be an odd number. Should be greater than 5. 7 works well. unsigned long a_second = 1000; float h = 0.0; //Stores humidity value float t = 0.0; //Stores temperature value float h_array[buff_size] = {0.0}; float t_array[buff_size] = {0.0}; float h_array_sort[buff_size] = {0.0}; float t_array_sort[buff_size] = {0.0}; String string_Temp, string_Humid, temporary_string, tick_string;

char OLED_string_1[50]; // Need a couple of character buffers to hold the two OLED lines char OLED_string_2[50];

String str_day, str_month, str_year, str_time; // Lot of conversion to strings required because the // DSD Tech display doesn't like integers and floats

void clearOLED() { u8g.firstPage(); do { } while( u8g.nextPage() ); }

void Initialize() { float startup_delay; int i; clearOLED(); startup_delay = buff_size * (a_second * 5.0 / 1000.0); temporary_string = String(startup_delay,0); temporary_string = " (" + temporary_string + " seconds)"; tick_string = "Initializing "; strcpy(OLED_string_1, tick_string.c_str());

strcpy(OLED_string_2, temporary_string.c_str()); // Take "buff_size" readings of each parameter, one every 5 seconds, // to get initial arrays of data. Print "status" dots across display. for (i = 0 ; i < buff_size ; i++) { tick_string = tick_string + ". "; strcpy(OLED_string_1, tick_string.c_str()); sendstringstoDisplay(); delay(a_second * 5); h_array[i] = dht.readHumidity(); // Get Humidity value t_array[i] = dht.readTemperature(); // Get Temperature value } }

void bubble_sort(float sort_array[], int n) { int i, j; float temp; for (i = 0 ; i < n - 1; i++) { for (j = 0 ; j < n - i - 1; j++) { if (sort_array[j] > sort_array[j+1]) { // Swap values temp = sort_array[j]; sort_array[j] = sort_array[j+1]; sort_array[j+1] = temp; } } } }

void sendstringstoDisplay() { u8g.firstPage(); // Send them to the dispaly do { u8g.setFont(u8g_font_5x7); // This can be adjusted to various fonts. See:

https://github.com/olikraus/u8glib/wiki/fontsize u8g.setPrintPos(0,7); // Position of first line u8g.print(OLED_string_1); u8g.setFont(u8g_font_helvB14); // Little biger and bolder font as this is the temperature and humidy u8g.setPrintPos(0, 25); // Position of second line u8g.print(OLED_string_2); } while (u8g.nextPage() ); }

void monthStr(tmElements_t tm) { int int_month; str_month = tm.Month; int_month = str_month.toInt(); switch(int_month) { case 1: str_month =("JAN"); break; case 2: str_month =("FEB"); break; case 3: str_month =("MAR"); break; case 4: str_month =("APR"); break; case 5: str_month =("MAY"); break; case 6: str_month =("JUN"); break; case 7: str_month =("JUL"); break; case 8:

str_month =("AUG"); break; case 9: str_month =("SEP"); break; case 10: str_month =("OCT"); break; case 11: str_month =("NOV"); break; case 12: str_month =("DEC"); break; default: str_month =("ERR"); break; } }

void timeStr(tmElements_t tm) { // Add a leading zero when needed so all numbers are two characters String hours,seconds,minutes; if(tm.Hour= (60000 * 2) && (temp24_isSent == false) ) { /* increase temp to 24 */ irsend.sendRaw(temp24, sizeof(power) / sizeof(temp24[0]), khz); //No the approach used to automatically calculate the size of the array. temp24_isSent = true; } /* increase the AC temperature from 24 to 25C if the time passed since on is >= 4sec */ if ( ac_time_passed >= (60000 * 4) && (temp25_isSent == false)) { /* increase temp to 25 */ irsend.sendRaw(temp25, sizeof(power) / sizeof(temp25[0]), khz); //Note the approach used to automatically calculate the size of the array. temp25_isSent = true; /* turn off auto-optimization since it's completed */ isAutoOptimize = false;

/* publish that auto-optimization has completed and is off now */ IOT.publish(ac_auto, "off", QOS_0); } } /************************************************* voice recognition *************************************************************/ //check if 1Sheeld's Arduino Voice Recognition Shield received a new command if (VoiceRecognition.isNewCommandReceived()) { //Compare the last command received by the Arduino Voice Recognition Shield with the command "on" if (!strcmp("light on", VoiceRecognition.getLastCommand())) { //Then turn the light on digitalWrite(light_pin, HIGH); } //Compare the last command received by the Arduino Voice Recognition Shield with the command "off" else if (!strcmp("light off", VoiceRecognition.getLastCommand())) { //Then turn the light off digitalWrite(light_pin, LOW); } //Compare the last command received by the Arduino Voice Recognition Shield with the command "play music" else if (!strcmp("play music", VoiceRecognition.getLastCommand())) { // play the music. MusicPlayer.play(0); // Terminal.println("play music now"); } //Compare the last command received by the Arduino Voice Recognition Shield with the command "pause music" else if (!strcmp("pause music", VoiceRecognition.getLastCommand())) { // pause the music. MusicPlayer.pause(); // Terminal.println("pause music now"); } } /********************************* Temperature & Gas sensors

*************************************/ /* Read DHT all data */ DHT.read11(TEMP_PIN); /* Read temperature */ temp = (int)DHT.temperature; /* read gas sensor */ gas_degree = analogRead(GAS_PIN); /* Convert sensors integers to char arrays */ itoa(temp, tempChar, 10); itoa(gas_degree, gas_degree_char, 10); /* Publish sensors' data */ IOT.publish(temperature, tempChar, QOS_0); IOT.publish(gas, gas_degree_char, QOS_0); /************************************************ Gas alarm ****************************************************/ /* check for gas dangerous level */ if ( gas_degree > 150 ) { /* blink the button led*/ digitalWrite(gas_switch_led_pin , HIGH); OneSheeld.delay(500); digitalWrite(gas_switch_led_pin , LOW); gas_HighLevelWarning = true; } else { /* turn off button led*/ digitalWrite(gas_switch_led_pin , LOW); gas_HighLevelWarning = false; alarm_isPressed = false; gas_emailSent = false; }

if( (gas_HighLevelWarning == true) && ( alarm_isPressed == false ) ) { /* Turn on the buzzer. */ Buzzer.buzzOn(); if(gas_emailSent == false)

{ /* Send an email with the last picture in OneSheeld folder. */ Email.send("[email protected]", "Dangerous Gas Alert!", "Hi, There is a dangerous level of gas in your home! Please check your dashboard."); /* delay for the email */ OneSheeld.delay(3000); /* prevent multiple sending*/ gas_emailSent = true; } } if( (interruptPin_isPressed == true) && (alarm_isPressed == false) ) { /* Turn off the buzzer. */ Buzzer.buzzOff(); alarm_isPressed = true; interruptPin_isPressed = false; } }

/* ###################################################################################### */ void newMessage(char * incomingTopic, char * payload, byte qos, bool retained) { /************************************************************************************** /* check for the speak topic */ if (!strcmp(speak, incomingTopic)) { /* If message is speak */ if (!strcmp("speak", payload)) { // this is for testing digitalWrite(test_led , HIGH); /* start listening to commands */ VoiceRecognition.start();

// this is for testing digitalWrite(test_led , LOW); } } /************************************************************************************** /* check for the light topic */

if (!strcmp(light, incomingTopic)) { /* If message is on */ if (!strcmp("on", payload)) { // this is for testing digitalWrite(test_led , HIGH); /* turn on light */ digitalWrite(light_pin , HIGH); // delay to notice the test led light OneSheeld.delay(200); // this is for testing digitalWrite(test_led , LOW); } /* If message is off */ else if (!strcmp("off", payload)) { // this is for testing digitalWrite(test_led , HIGH); /* turn off light */ digitalWrite(light_pin , LOW); // delay to notice the test led light OneSheeld.delay(200);

// this is for testing digitalWrite(test_led , LOW); } } /************************************************************************************** /* check for the cam_cap topic */ if (!strcmp(cam_cap, incomingTopic)) { /* If message is capture */ if (!strcmp("capture", payload)) { // this is for testing digitalWrite(test_led , HIGH); /* Take a photo for that stranger using the phone's front camera */

Camera.frontCapture(); /* delay for the camera */ OneSheeld.delay(8000); /* Send an email with the last picture in OneSheeld folder. */ Email.attachLastPicture("[email protected]", "Home Camera", "Hi, here is a photo of your home", 1); /* delay for the email */ OneSheeld.delay(3000);

// this is for testing digitalWrite(test_led , LOW); } } /************************************************************************************** /* check for the cam_dir topic */ if (!strcmp(cam_dir, incomingTopic)) { /* If message is 0 */ if (!strcmp("0", payload)) { /* Start servo at the 180 degree angle */ servo_for_loop(CamServo.read() , 180); } /* If message is 1 */ else if (!strcmp("1", payload)) { /* Start servo at the 135 degree angle */ servo_for_loop(CamServo.read() , 135); } /* If message is 1 */ else if (!strcmp("2", payload)) { /* Start servo at the 90 degree angle */ servo_for_loop(CamServo.read() , 90); } /* If message is 3 */ else if (!strcmp("3", payload)) { /* Start servo at the 45 degree angle */

servo_for_loop(CamServo.read() , 45); }

/* If message is 4 */ else if (!strcmp("4", payload)) { /* Start servo at the 0 degree angle */ servo_for_loop(CamServo.read() , 0); } } /************************************************************************************** /* check for the ac topic */ if (!strcmp(ac, incomingTopic)) { /* If message is on */ if (!strcmp("on", payload)) { // this is for testing digitalWrite(test_led , HIGH); /* turn on ac */ irsend.sendRaw(power, sizeof(power) / sizeof(power[0]), khz); //Note the approach used to automatically calculate the size of the array. // this is for testing digitalWrite(test_led , LOW); } /* If message is off */ else if (!strcmp("off", payload)) { // this is for testing digitalWrite(test_led , HIGH); /* turn on ac */ irsend.sendRaw(power, sizeof(power) / sizeof(power[0]), khz); //Note the approach used to automatically calculate the size of the array.

// this is for testing digitalWrite(test_led , LOW); } } /************************************************************************************** /* check for the auto-optimization ac topic */ if (!strcmp(ac_auto, incomingTopic)) {

/* If message is on */ if (!strcmp("on", payload)) { // this is for testing digitalWrite(test_led , HIGH); /* turn on ac */ ac_start_time = millis(); // turn on auto optimization isAutoOptimize = true; // this is for testing digitalWrite(test_led , LOW); } /* If message is off */ else if (!strcmp("off", payload)) { // this is for testing digitalWrite(test_led , HIGH); // turn off auto optimization isAutoOptimize = false;

// this is for testing digitalWrite(test_led , LOW); } } } /************************************************************************************** void connectionStatus(byte statusCode) { /* Check connection code and display. */ switch (statusCode) { case CONNECTION_SUCCESSFUL: Terminal.println("CONNECTION_SUCCESSFUL"); break; case CONNECTION_FAILED: Terminal.println("CONNECTION_FAILED"); break; case CONNECTION_LOST: Terminal.println("CONNECTION_LOST"); break; case CONNECTION_LOST_RECONNECTING: Terminal.println("CONNECTION_LOST_RECONNECTING"); break; case NOT_CONNECTED_YET: Terminal.println("NOT_CONNECTED_YET"); break; case MISSING_HOST: Terminal.println("MISSING_HOST"); break; } }

/************************************************************************************** void error(byte errorCode) { /* Check error code and display. */ switch (errorCode) { case CONNECTION_REFUSED : Terminal.println("CONNECTION_REFUSED"); break; case ILLEGAL_MESSAGE_RECEIVED : Terminal.println("ILLEGAL_MESSAGE_RECEIVED"); break; case DROPPING_OUT_GOING_MESSAGE : Terminal.println("DROPPING_OUT_GOING_MESSAGE"); break; case ENCODER_NOT_READY : Terminal.println("ENCODER_NOT_READY"); break; case INVALID_CONNACK_RECEIVED : Terminal.println("INVALID_CONNACK_RECEIVED"); break; case NO_CONNACK_RECEIVED : Terminal.println("NO_CONNACK_RECEIVED"); break; case CONNACK_UNACCEPTABLEP_ROTOCOLVERSION : Terminal.println("CONNACK_UNACCEPTABLEP_ROTOCOLVERSION"); break; case CONNACK_IDENTIFIER_REJECTED : Terminal.println("CONNACK_IDENTIFIER_REJECTED"); break; case CONNACK_SERVER_UNAVAILABLE : Terminal.println("CONNACK_SERVER_UNAVAILABLE"); break; case CONNACK_AUTHENTICATION_FAILED : Terminal.println("CONNACK_AUTHENTICATION_FAILED"); break; case CONNACK_NOT_AUTHORIZED : Terminal.println("CONNACK_NOT_AUTHORIZED"); break; case CONNACK_RESERVED : Terminal.println("CONNACK_RESERVED"); break; } }

/************************************************************************************** /* A function that makes the whole operation of the ultrasonic and returning the detected distance */ int getUltrasonicDistance(void) { /* Variable to save the sound wave travel time in microseconds */ long duration; /* Variable to save the detected distance in cm */ int distanceReturned; /* Clears the trigPin */

digitalWrite(trigPin, LOW); /* delay 2 micro seconds */ delayMicroseconds(2); /* Sets the trigPin on HIGH state for 10 micro seconds */ digitalWrite(trigPin, HIGH); /* delay 10 micro seconds */ delayMicroseconds(10); /* Sets the trigPin on LOW state */ digitalWrite(trigPin, LOW); /* Reads the echoPin, returns the sound wave travel time in microseconds */ duration = pulseIn(echoPin, HIGH);

/* Calculating the distance */ distanceReturned = duration * 0.034 / 2; /* Returning the detected distance in cm */ return distanceReturned; }

/************************************************************************************** void servo_for_loop(int start_angle , int stop_angle) { if( start_angle < stop_angle ) { for( ; start_angle stop_angle ) { for( ; start_angle >= stop_angle ; start_angle-- ) { CamServo.write(start_angle); delay(25); } } } /**************************************************************************************

void interruptPin_isr() { interruptPin_isPressed = true; }

202) Arduino Attiny85/84 with Bluetooth

COMPONENTS AND SUPPLIES Capacitor 10 µF ×

1

×

1

×

1

×

1

×

1

×

1

Microchip ATtiny85

Arduino UNO & Genuino UNO

LED (generic)

Jumper wires (generic)

HC-05 Bluetooth Module

APPS AND ONLINE SERVICES Arduino IDE

MIT App Inventor 2

ABOUT THIS PROJECT Here I have used HC -05 bluetooth module which can be purchased from ebay at a very low cost.eto Attiny85/84 .In this tutorial I won't be going in detail about how to upload the sketchs to Attiny85/84. I also hope that you are familiar with arduino and bluetooth concepts If no you can accept google as your teacher. Setup

Here in this tutorial I will show you how to start serial communication with the ATiny85 over a Bluetooth network. First upload the following sketch to Attiny85. Make sure that you burn 8mz boot loader to Attiny before uploading the sketch. Knowing your Bluetooth Connection

Here I have used HC -05 bluetooth module which can be purchased from ebay at a very low cost. Refer the following image to identify the

pin diagram of Hc-05 module.

Now connect the Attiny 85 to Hc-05 module as given below. Bluetooth Module Rx --> ATiny85 Pin 1 Bluetooth Module Tx --> ATiny85 Pin 2 Bluetooth Module Gnd --> ATiny85 GND Bluetooth Module VCC --> ATiny85 VCC LED pin -->ATiny85 Pin4

Getting it all Connected Connect every Attiny85 as shown above .Now to check weather the serial communication works between bluetooth module and Attiny85 download the apk(Dime.apk) file provided in the attachment. This app was made by using MIT App inventor. You too can edit this I have attached an aia(Dime.aia) file below. How to use the Bluetooth App? Make sure that the Attiny and bluetooth is powered .

Open the app then click on the bluetooth icon in the app and select the HC-05 from the list.(Before connecting you have to make sure that HC05 is paired with the mobile).Once the HC-05 is connected the text will show as"Connected".

Now shake your phone and see that the led blinks. You can even use a relay instead of led and control the home appliances.

SCHEMATICS

CODE #include //Software Serial Port #define RxD 1 #define TxD 2 #define DEBUG_ENABLED 1 SoftwareSerial blueToothSerial(RxD,TxD);

int led = 4; void setup() { pinMode(RxD, INPUT); pinMode(TxD, OUTPUT); setupBlueToothConnection(); pinMode(led,OUTPUT); digitalWrite(led,HIGH); } void loop() { int count=0; char recvChar; while(1){ //check if there's any data sent from the remote bluetooth shield if(blueToothSerial.available()){ recvChar = blueToothSerial.read(); count++ ; if(count%2==0) digitalWrite(led,HIGH); else digitalWrite(led,LOW); } } } void setupBlueToothConnection() { blueToothSerial.begin(9600); //Set BluetoothBee BaudRate to default baud rate 38400

blueToothSerial.print("\r\n+STWMOD=0\r\n"); //set the bluetooth work in slave mode blueToothSerial.print("\r\n+STNA=HC-05\r\n"); //set the bluetooth name as "HC-05" blueToothSerial.print("\r\n+STOAUT=1\r\n"); // Permit Paired device to connect me blueToothSerial.print("\r\n+STAUTO=0\r\n"); // Auto-connection should be forbidden here delay(2000); // This delay is required. //blueToothSerial.print("\r\n+INQ=1\r\n"); //make the slave bluetooth inquirable blueToothSerial.print("bluetooth connected!\n"); delay(2000); // This delay is required. blueToothSerial.flush(); }

203) Arduino Flying Drone Mjolnir with Hacked RC Transmiter

COMPONENTS AND SUPPLIES Arduino UNO & Genuino UNO

Adafruit LIS3DH Accelerometer AD5206 10K digital potentiometer

×

1

×

1

×

1

ABOUT THIS PROJECT Mjolnir is Thor's trusty hammer, and will always return to his hand when thrown (as depicted in the Marvel Cinematic Universe, anyhow). So how do we build our own legendary flying hammer? With Arduinos,

of course! The heart of this hammer is not a dying star, but rather a micro racing drone. The hammer itself is a foam and balsa wood frame built around the quadcopter with plenty of open areas for air flow. The true test of worthiness, however, is throwing Mjolnir and summoning it back to your hand. That trick is done with an Arduino Uno controlling the quadcopter transmitter via digital potentiometers. Push buttons mounted to a wrist brace control pitch and throttle, and an accelerometer maps hand movements to the quadcopter's roll. With some patience, this makes Mjolnir controllable with one hand, leaving your other hand free to catch Thor's hammer! This is not a beginner project, and a lot of the hammer's design was modified on the fly (pun intended), so the final product doesn't map perfectly to the provided CAD files. There's also a ton of variability in receivers and transmitters, so you will need strong troubleshooting and trial-and-error skills, and even then Mjolnir handles like a fat cow in the air. You have been warned! Hammer Materials:

The hammer body is mostly made of foam sheet is from Dollar Tree; you'll have to peel off the paper lamination before you begin constructing the hammer! A rectangular frame made of balsa wood holds the quadcopter in place, it's made by laminating two 1/8" thick parts with Titebond III for strength. The adhesives used are 3M 78 for gluing foam to foam, hot glue for everything else, and foam safe CA glue to fix boo-boos after crashes.

The svg used for laser cutting the parts are all on this page. For the foam, all the angled edges were beveled to 22.5 degrees with a utility knife before being glued together. The faces of the hammer are hot glued to the head because the edges didn't line up, and a fillet of glue was needed for structure. The handle of the hammer was not laser cut, because it's just a 4"x10" rectangle of foam rolled up and hot glued shut along the seam.

The frame is the tricky bit, the included files are an older design where the quadcopter was higher up in the hammer. It turns out that the props need to be very close to the bottom of the hammer head to work properly. So in the final design, just the outer rectangular shape of the frame is kept and the prop guards of the quadcopter are incorporated into the structure. The quadcopter used here is an Emax Babyhawk running on a 3S 260mAh Lipo battery, which is tucked into a box above the handle (which was ultimately made to fit the dimensions of the battery by hand, rather than the laser cut part). The handle and battery box are hot glued to the bottom of the quadcopter.

Setting up the Babymax is a whole other tutorial on it's own which is covered extensively elsewhere. I used a Spektrum DSMX racing receiver, which is hot glued to the Babymax camera mount, with the

camera gutted since we don't need FPV of the inside of a hammer and it saves a few grams of weight. You'll notice the hammer is two separate parts, with a "base" hot glued directly to the prop guards of the quadcopter, and a top "case" that rests on top. Two rectangular strips of foam were glued to the base to help guide the case on top of the base, and a small set of neodymium magnets secures the case to the base.

Don't forget the paint! Normal spray paints will eat away your beautiful foam creation, so you'll need to use an acrylic paint. If you're fancy, use an airbrush, if you're just a little less fancy like me, use an acrylic based spray paint like Liquitex.

Opening the Transmitter This technique should work on any RC transmitter with potentiometer joysticks. We're going to be adding 3 wire connectors so the joysticks can be bypassed and the transmitter directly controlled by an Arduino via AD5206 10K digital potentiometer.

Splice in to the Potentiometers I used servo extension cables, that way the transmitter can easily be used as normal or connected to an Arduino. Make sure you label your wires! Drill some holes into the transmitter back for the wires to come out from, and close the transmitter back up.

This switch is mapped as the "arm" switch in betaflight. I'll also be adding an extension wire to this

Connect to Arduino via AD5206 Check out the code included with this tutorial! Refer to your datasheet, the code, and your transmitter to work out wiring the potentiometer to the transmitter. Match the transmitter pot's ground, wiper, and v+ to b, w, and a of the digital pot. This Arduino tutorial is a good resource. Find a couple push buttons and an LIS3DH accelerometer (same one used for firebending!) and connect them as shown in the schematic attached to this tutorial. You'll notice a toggle switch in parallel to a pushbutton switch as input to pin 6; that represents whatever you've chosen as the arm switch on your transmitter. The push button becomes your new arm switch, and the Arduino simply reads the state of the switch so it knows when to throttle up or down. Load up the included code, plug your Babyhawk into your computer and connect to Betaflight Configurator, and do a system test! You should be able to see the receiver values change by pressing the buttons and tilting the accelerometer.

Mount the Electronics I used a wrist brace to mount the throttle button, pitch button, and accelerometer. They connect to the Arduino Uno through about 3 feet of wire. The transmitter, Arduino Uno, and digital pot are all just taped to a board of wood with foam mounting tape. Everything fits into a fashionable red sling backpack!

Are You Worthy?! Mjolnir flies about as well as you'd expect a brick shaped object to fly. Any slight gusts of wind knock the poor thing around like crazy, and there isn't really a good way to launch or land. Almost every time the

hammer "lands", the handle will probably break off. But that's what glue's for! After a solid day of filming I managed the successfully "throw" and catch Mjolnir about twice, but both times the shock of catching the hammer ended up breaking it. What I'm saying is there is lots of room for improvement here! (Especially since I used the stock PID settings XD) SCHEMATICS

CODE // include the SPI library: #include #include #include #include // set pin 10 as the slave select for the AD5206 digital pot: const int slaveSelectPin = 10; int accelValue = 0; int rollValue = 0; int rollValuePrev = 0; int throttleValue = 0; int pitchValue = 0; // two buttons for pitch and throttle const int pitchPin = 7; const int throtPin = 6; int throttle = 0; int roll = 1; int pitch = 2; int flag = 0; int pitchFlag = 0; //value must be determined empirically: int maxThrottle = 120; // I2C Adafruit_LIS3DH lis = Adafruit_LIS3DH(); void setup() { // set the slaveSelectPin as an output: pinMode(slaveSelectPin, OUTPUT); pinMode(pitchPin, INPUT_PULLUP);

pinMode(throtPin, INPUT); // initialize SPI: SPI.begin(); Serial.begin(9600); Serial.println("LIS3DH test!"); if (! lis.begin(0x18)) { // change this to 0x19 for alternative i2c address Serial.println("Couldnt start"); while (1); } Serial.println("LIS3DH found!"); lis.setRange(LIS3DH_RANGE_2_G); // 2, 4, 8 or 16 G! Serial.print("Range = "); Serial.print(2 250){ Serial.print("Interrupt "); Serial.print(y++); Serial.println(); ledToggle = !ledToggle; digitalWrite(ledPin, ledToggle); last_button_time = button_time; } } Why that millis() used ? One common problem with interrupts is they often can trigger multiple times for a single event. if you press the button just once, y will increment many times. A button push might seem like a single step, but in reality the mechanical parts within that button come into contact multiple times before settling into a particular state. There are several ways to remedy this. Often you can fix bounce issues with hardware by adding an appropriate RC filter to smooth the transition. Another option is to address it in software by temporarily ignoring further interrupts for a small time frame after the first interrupt is triggered. that's why millis() is used here.

result Here controller immediately shifting from loop to interrupt service routine.This is how an Interrupt can be useful to trigger any important task in between of normal execution. Interrupt Priority Levels What happens when two interrupts occur at the same time? Most AVRs do

not support what we call interrupt priority levels. Should two interrupts occur simultaneously or there are two or more interrupts waiting in a queue, the priority is determined by the order of their vector addresses. Lower vector addresses are serviced first, Reset will take precedence over all interrupt requests. Again, your datasheet will have more information on your specific board.

SCHEMATICS

CODE const int ledPin = 12; //ledPin const int buttonPin = 2; //Button to perform interrupt int x=0, y=0; //some variables to increment int ledToggle = LOW; //led state //variables to keep track of the timing of recent interrupts unsigned long button_time = 0; unsigned long last_button_time = 0; void setup() { pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT_PULLUP); Serial.begin(9600); attachInterrupt(digitalPinToInterrupt(buttonPin), button_ISR, CHANGE); } void loop(){ Serial.print("loop " ); Serial.print(x++ ); Serial.println(); delay(500); } void button_ISR(){ button_time = millis(); //check to see if increment() was called in the last 250 milliseconds if (button_time - last_button_time > 250){ Serial.print("Interrupt "); Serial.print(y++); Serial.println(); ledToggle = !ledToggle; digitalWrite(ledPin, ledToggle); last_button_time = button_time; } }

207) Arduino Air Quality Monitor

COMPONENTS AND SUPPLIES Arduino Nano R3 ×

1

DSM501A Dust sensor module

×

1

×

1

×

1

×

5

×

1

×

1

Alphanumeric LCD, 16 x 2

Fan kit 40mm LED (generic)

Resistor 221 ohm

Single Turn Potentiometer- 10k ohms

NECESSARY TOOLS AND MACHINES Soldering iron (generic)

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT Air quality monitoring is well known and established science which started back in the '80s. At that time, the technology was quite limited, and the solution used to quantify the air pollution complex, cumbersome and really expensive. Fortunately, nowadays, with the most recent and modern technologies, the solutions used for air quality monitoring are becoming not only more precise, but also faster at measuring. Devices are becoming smaller, and cost much more affordable than ever before. The presented device uses the Samyoung "DSM501A" dust sensor which is one of the cheapest on the market and can be purchased at AliExpress for a few dollars.This sensor is capable of detecting PM2.5 as well as PM10 particles. In the picture below, you can see the layout of the pins but don't pay attention to the color of the wires as they may be different.

The circuit is very simple: Vout1 (PM2.5) from sensor is connected to D2 of Arduino, Vout2 (PM10) to D3, Vcc to Arduino +5V, and GND to Arduino Gnd pin. The LED diodes are connected to the analog pins A1 to A5 of Arduino which are defined as outputs in the code.LCD display with 61x2 characters is compatible with the Hitachi HD44780. It shows the concentration of PM10 particles in pcs/0.01cf, and 5 states of air quality: - Clean - Good - Acceptable - Heavy - Hazard The concentration of both PM10 and PM2.5 can be monitored on the

arduino serial monitor. Depending on the degree of contamination(PM10), an appropriate LED of a certain color will be lit to allow a quick and easy reading of the result. I don't have much experience in writing codes, so maybe the code can be improved. It is very important to emphasize that by installing a fan that draws air out of the sensor outlet, significantly improve the characteristics in the area of unwanted peak values. The whole device is assembled in a plastic box for electrical installation.

SCHEMATICS

CODE #include LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int pin2 = 3; int pin1 = 2; unsigned long duration1; unsigned long duration2; unsigned long starttime; unsigned long sampletime_ms = 3000;//sampe 1s ; unsigned long lowpulseoccupancy1 = 0; unsigned long lowpulseoccupancy2 = 0; float ratio1 = 0; float ratio2 = 0; float concentration1 = 0; float concentration2 = 0; int wLed = A1; int gLed = A2; int yLed = A3; int rLed = A4; int bLed = A5; void setup() { Serial.begin(9600); pinMode(2,INPUT); pinMode(3,INPUT); pinMode(wLed,OUTPUT); pinMode(gLed,OUTPUT); pinMode(yLed,OUTPUT); pinMode(rLed,OUTPUT); pinMode(bLed,OUTPUT); starttime = millis();//get the current time; lcd.begin(16, 2); } void loop() { duration1 = pulseIn(pin1, LOW); duration2 = pulseIn(pin2, LOW); lowpulseoccupancy1 = lowpulseoccupancy1+duration1; lowpulseoccupancy2 = lowpulseoccupancy2+duration2;

if ((millis()-starttime) > sampletime_ms)//if the sampel time == 30s { ratio1 = lowpulseoccupancy1/(sampletime_ms*10.0); // Integer percentage 0=>100 concentration1 = 1.1*pow(ratio1,3)-3.8*pow(ratio1,2)+520*ratio1+0.62; // using spec sheet curve ratio2 = lowpulseoccupancy2/(sampletime_ms*10.0); // Integer percentage 0=>100 concentration2 = 1.1*pow(ratio2,3)-3.8*pow(ratio2,2)+520*ratio2+0.62; // lcd.setCursor(0, 0); lcd.print("PM10 "); lcd.setCursor(6, 0); lcd.print(concentration1,3); Serial.print("concentration1 = "); Serial.print(concentration1); Serial.print(" pcs/0.01cf - "); Serial.print("concentration2 = "); Serial.print(concentration2); Serial.print(" pcs/0.01cf - ");

if (concentration1 < 1000) { lcd.setCursor (0, 1); for (int i = 0; i < 16; ++i) { lcd.write(' '); } lcd.setCursor(4, 1); lcd.print("CLEAN"); digitalWrite(wLed, HIGH); digitalWrite(gLed, LOW); digitalWrite(yLed, LOW); digitalWrite(rLed, LOW); digitalWrite(bLed, LOW); } if (concentration1 > 1000 && concentration1 < 10000) { lcd.setCursor (0, 1); for (int i = 0; i < 16; ++i) { lcd.write(' ');

} lcd.setCursor(4, 1); lcd.print("GOOD"); digitalWrite(wLed, LOW); digitalWrite(gLed, HIGH); digitalWrite(yLed, LOW); digitalWrite(rLed, LOW); digitalWrite(bLed, LOW); } if (concentration1 > 10000 && concentration1 < 20000) { lcd.setCursor (0, 1); for (int i = 0; i < 16; ++i) { lcd.write(' '); } lcd.setCursor(4, 1); lcd.print("ACCEPTABLE"); digitalWrite(wLed, LOW); digitalWrite(gLed, LOW); digitalWrite(yLed, HIGH); digitalWrite(rLed, LOW); digitalWrite(bLed, LOW); } if (concentration1 > 20000 && concentration1 < 50000) { lcd.setCursor (0, 1); for (int i = 0; i < 16; ++i) { lcd.write(' '); } lcd.setCursor(4, 1); lcd.print("HEAVY"); digitalWrite(wLed, LOW); digitalWrite(gLed, LOW); digitalWrite(yLed, LOW); digitalWrite(rLed, HIGH); digitalWrite(bLed, LOW); } if (concentration1 > 50000 ) { lcd.setCursor (0, 1); for (int i = 0; i < 16; ++i)

{ lcd.write(' '); } lcd.setCursor(4, 1); lcd.print("HAZARD"); digitalWrite(wLed, LOW); digitalWrite(gLed, LOW); digitalWrite(yLed, LOW); digitalWrite(rLed, LOW); digitalWrite(bLed, HIGH); } lowpulseoccupancy1 = 0; lowpulseoccupancy2 = 0; starttime = millis(); } }

208) Arduino Contyrol AC Water Heater Temperature

COMPONENTS AND SUPPLIES

Breadboard (generic) ×

1

×

1

×

1

×

1

×

1

×

1

Jumper wires (generic)

Arduino Nano R3

Adafruit OLED 0.96 LCD Adafruit Waterproof DS18B20 Digital temperature sensor

Resistor 4.75k ohm

APPS AND ONLINE SERVICES Arduino IDE

ABOUT THIS PROJECT This is one of the most interesting and hardest experiment to do, Why? because the circuit we want to build is a little bit hard and tricky. Most of the tutorial in the internet do it with relay to turn on-off the AC heater to increase the temperature,it's not an accurate way to control the water temperature,and will not be able to reach to your target temperature. To explain it in a simple example: you want to increase a temperature of the water to be about 60 degree Celsius,With a relay when you reach to 60 degree Celsius,the relay turn off the Heater, that makes the temperature decrease rapidly so the relay will turn on and increase temperature rapidly again , so the relay will turn on-off within a short time which will damage the relay and maybe damage the heater it self. Best way to adjust the temperature by control AC voltage output applied on AC heater. build a (crappy) AC triac circuit not just unprofessional but also will not work well,With inappropriate heatsink,no protection from ac short circuit or overload current, and most important no protection for you,any small fault might kill you,be careful.

Example of unprotected circuit So let's see the best way to control AC heater, and offer a high protection from electrical shock hazard,and give us a full control over the water temperature. We want to control AC Water heater, and control the water target temperature with temperature sensor feedback signal,and we want to control Applied AC voltage on the AC water heater so we can control accurately the water temperature. We will use an LCD to show all information an parameters on it. the components we need are:

Arduino Board"I used arduino Nano". AC water heater 300W. Sugar Device "I used Sugar300". Power Cable C14. OLED 0.96 inch display. DS18B20 water proof temperature sensor. 4.7K resistor RJ12 Cable. RJ Breakout. Breadboard and solderless jumper Oscillscope"optional".

As we see no need for any naked wire, or cutting any AC wires to connect the components together "like in the relay circuits". and we will use an oscilloscope to see the AC voltage waveform and ensure the sugar device control the applied ac voltage on water heater. in the final all you need to do is Connect to connect the water heater element to Sugar device output socket. Connect the AC power cable to sugar device to power it up. connect the RJ12 cable between sugar device and arduino, use RJ breakout to connect the cable to Arduino nano.

and you need a glass of water too put the heater inside it with the DS18B20 sensor

well during this test, i faced something may happen for everyone, the power consumption by the AC Heater was larger than 300W and the AC current was higher than I expected, thanks for Sugar device , the ac fuse protect the circuit and cut off the power source, for such a circumstances,Sugar is capable to protect your self and equipment you use from any short circuit or overload fault.

all similar circuits on the internet won't do that, you will be under the mercy of AC current which will damage all unprotected component and put you life under threat. remember safety is a priority. and with sugar I safely remove the fuse and replace it by a new one,no need to open the device or touch any dangerous ac components. last thing to say:you need to observe the temp target and the sensor temp and adjust the value of the output voltage in the code go to "" void UpdatePWM() "" and change the value to match your requirements

SCHEMATICS

CODE #include #include #include #include #include #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_RESET); OneWire ds(2); // on pin 2 (a 4.7K resistor is necessary) const int SugarPin =9; int HeaterPWM=13; int voltage_perc; const int delayTime=1000; float Temp;

float T_diff=0.0; float Target_T=90; int MenuCounter=1; #if (SSD1306_LCDHEIGHT != 64) #error("Height incorrect, please fix Adafruit_SSD1306.h!"); #endif void setup() { display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); display.display(); // define arduino PWM as an output pinMode(SugarPin,OUTPUT); //define Button as an input with PullUp resistor // pinMode(Sugar_Pot ,INPUT); MainMenu(); display.display(); delay(3000); display.clearDisplay(); display.display(); ControlPanel(); } void MainMenu() { display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(20,5); display.print("Sugar"); display.setCursor(20,35); display.print("Device"); delay(3000); } void UpdateReading() { display.setTextSize(3); display.setCursor(20,30); display.setTextColor(WHITE); switch(MenuCounter) { case 1: display.print(Target_T); break; case 2: display.print(Temp); break;

case 3: display.print(voltage_perc); break; } display.display(); MenuCounter++; if(MenuCounter>3){MenuCounter=1;} } void ControlPanel() { display.clearDisplay(); display.display(); display.setTextSize(2); display.setTextColor(WHITE); switch(MenuCounter) { case 1: display.setCursor(5,5); display.print("Sensor T"); break; case 2: display.setCursor(5,5); display.print("Target T"); break; case 3: display.setCursor(5,5); display.print("AC volt%"); break; } display.display(); } void loop() { ReadTempSensor(); delay(500); ControlPanel(); UpdatePWM(); UpdateReading(); } void UpdatePWM() { T_diff=Target_T-Temp; if(T_diff>=40)

{ HeaterPWM=64;//full voltage; voltage_perc=100; } else if(T_diff=30 ) { HeaterPWM=54;//full voltage; voltage_perc=85; } else if(T_diff=20 ) { HeaterPWM=48; //60% voltage_perc=75; } else if(T_diff=10 ) { HeaterPWM=38; //50% voltage_perc=50; } else if(T_diff=2 ) { HeaterPWM=30; //30% voltage_perc=30; } else if(T_diff