0% found this document useful (0 votes)
148 views

Elif Avcu - 220 Fun Projects With Arduino (2020)

Uploaded by

Alex Orange
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
148 views

Elif Avcu - 220 Fun Projects With Arduino (2020)

Uploaded by

Alex Orange
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3101

220 Fun Projects with Arduino

1) Arduino Hacking STEM Electroconductivity Meter

COMPONENTS AND SUPPLIES

biodegradable straw
× 1

coffee stir stick


× 2
stainless steel wire (28 gauge, × 2
17cm)

pin-ended alligator clips


× 2

Resistor 100 ohm

× 1

Arduino UNO & Genuino UNO

× 1

USB-A to B Cable

× 1
NECESSARY TOOLS AND MACHINES
scissors

Wire Stripper & Cutter, 18-10 AWG / 0.75-


4mm² 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 POWER_PIN = 2; // Digital pin to use for powering pulse circuit
const byte EC_PIN = A0; // Analog pin used to read EC Meter volage
const int READ_DURATION = 100; // Amount of time to take reading for (ms)
const int READ_INTERVAL = 6000; // Amount of time between readings (ms)

const String SERIAL_OUTPUT_DELIMITER = ","; // Cordoba expects a comma-


delimited string
const int SERIAL_OUTPUT_INTERVAL = 175; // Amount of time between serial
outputs

// TIMESTAMPS

unsigned long currentTime = 0;


unsigned long readStartTime = 0; // Time that the EC Meter read process starts
unsigned long lastOutputTime = 0; // 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 <= readStartTime ) // Power Up / Read
{
startPower( POWER_PIN ); // Start charging solution
delay(250); // Delay until fully charged
readSensors(); // Take sensor readings
delay(250);
} else { // Power Down
stopPower( POWER_PIN ); // Stop charging and let solution
depolarize
}

writeToSerial();
}

/*
-------------------------------------------------------------------------------------------------------
SENSOR/ARDUINO PROCESSING
-------------------------------------------------------------------------------------------------------
*/

void startPower( byte pin ){


digitalWrite( pin , HIGH );
}

void stopPower ( byte pin ){


digitalWrite( pin , LOW );
}

void readSensors() {
ecMeterReading = analogRead( EC_PIN ); // read the voltage from the EC Meter
ecMeterVoltage = ecMeterReading * 5.0;
ecMeterVoltage = ecMeterVoltage / 1024;
}

/*
-------------------------------------------------------------------------------------------------------
OUTGOING SERIAL DATA TO EXCEL PROCESSING CODE
-------------------------------------------------------------------------------------------------------
*/

void writeToSerial()
{
// Ignore if not within output interval
if ( currentTime - lastOutputTime < SERIAL_OUTPUT_INTERVAL ) {
return;
}
Serial.print( ecMeterVoltage , 4 );
Serial.print( SERIAL_OUTPUT_DELIMITER );

Serial.println();

lastOutputTime = currentTime;
}
2) Arduino Cockroach Laser Killer

COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1
SG90 Micro-servo motor
× 1

LDR sensor
× 1

Resistor 10k ohm

× 1

Jumper wires (generic)

× 1

Breadboard (generic)
The 170 points breadboard
× 1

9V battery (generic)

× 1

9V Battery Clip

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

If you feel terrified about cockroaches...


You problem is now solved with " Cockroach Laser Killer!
No more embarrassing excuses to run off from them!

Okay...this is a simple LDR and Servo interaction. Geta laser pen and
"shoot" at the target. LDR activates a servo motor to drop your target
down. 3 seconds later it goes up again for another shot.
The main issue is to set the correct threshold of the LDR sensor and avoid
unwanted movements due to light conditions.
A 7cm x 7cm box.
The inital setup. When energized, the servo lifts the target.
The target arised and the laser gun!
Creepy!
In the box with a smal breadboard.

SCHEMATICS
CODE

/*
Project - Interaction LDR x Servo
*/
#include <Servo.h>

Servo servo1; // Servo object


int pinServo = 2; // variable to store the servo position
int triggerPoint = 970; //trigger point to start servo
byte sensor = A0;
int sensorValue;

void setup() {
pinMode(pinServo, OUTPUT);
servo1.attach(pinServo); // attaches the servo pin
servo1.write(155);// tell servo to go to "up" position
delay(200);
pinMode(sensor, INPUT);
}

void loop() {
sensorValue = analogRead(sensor);
if (sensorValue > triggerPoint){
servo1.write(75); // tell servo to go to "down" position
delay(3000);
servo1.write(155);
delay(200);
}
}//End loop

3) Controlled Board Eraser Using Arduino and 1Sheeld


COMPONENTS AND SUPPLIES
Android device

× 1

Arduino UNO & Genuino UNO

× 1

1Sheeld

× 1
Micro Metal DC motor kit
× 2

L298 Dual H-Bridge Motor Driver


× 1

Magnetic Disk
× 2

LED (generic)

× 1
NECESSARY TOOLS AND MACHINES

Magnetic Board Eraser

ABOUT THIS PROJECT

Are you tired of erasing the board every time you use it. Have you ever
thought of erasing the whole board while you are sitting in your place. The
automatic board eraser is a normal magnetic board eraser with motors and
wheels that can easily erase and clean your board using your mobile
phone. Just leave it mounted on the board and use it when you need to
erase.

Why did i decide to make it ?

Most of the people nowadays use white boards in classes or meeting


rooms. They write a lot and erase every time when they finish. There are
some disadvantages from erasing the whole board physically with your
hand, like wasting some time, doing effort, not professional in some
meetings for important people to do it themselves and it the eraser makes
your hands more dirty after using it. Moreover, some people find it hard to
reach all the parts of the board especially when it is mounted on a high
distance from the ground. As a result, I decided to build a small magnetic
automated board eraser with wheels so i could control it easily from my
mobile phone to erase the board from my place.

How Does it work?

After connecting all the hardware components and uploading the code to
the arduino and 1sheeld start opening the 1sheeld mobile application and
connect it to the 1sheeld board via Bluetooth. Then you have to select the
shields that we will use; they are the game pad shield and accelerometer
shield. Put the eraser on the board and open the game pad shield and start
using the four arrow directions to move up, down, left or right. An LED
will be high when the magnetic eraser moves on the board to start erasing
words. Another way to control this eraser is to open the accelerometer
shield and hold the phone in your hand. If you want to move up tilt your
hand in the front direction to make the Y < -5, so the eraser will move
up. If you want to move down tilt your hand in the backward direction to
make the Y < 6, so the eraser will move down. Furthermore, if you want to
move right tilt your hand in the right direction to make the x < -6, so the
eraser will move in the right direction and finally If you want to move left
tilt your hand in the left direction to make the x > 6, so the eraser will
move in the left direction. Now your board will be easily controlled to
erase the whole board without doing any effort.

Images of hardware Components


Magnetic Board Eraser
Micro metal DC motors and wheels
Motor Driver L289n
Motors connected to motor driver
1sheeld Board
Gloves used to control the board eraser using mobile accelerometer
Top view of the Eraser

Game pad used to control the eraser


Magnetic Board Eraser Final Prototype

SCHEMATICS
CODE

#define CUSTOM_SETTINGS
#define INCLUDE_GAMEPAD_SHIELD
#define INCLUDE_LED_SHIELD
#define INCLUDE_ACCELEROMETER_SENSOR_SHIELD

float x, y, z;

/* Include 1Sheeld library. */


#include <OneSheeld.h>

/* A name for the LED on pin 7. */


const int ledPin = 13;

/* Pin configuration of the Seeedstudio's motor shield. */


int motorAPin1 = 8;
int motorAPin2 = 11;
int motorBPin1 = 12;
int motorBPin2 = 7;
int motorASpeedPin = 9;
int motorBSpeedPin = 10;

void setup()
{
/* Start communication. */
OneSheeld.begin();
/* Set the LED pin as output. */
pinMode(ledPin, OUTPUT);

/* Seeedstudio's motor shield initialization. */


pinMode(motorAPin1, OUTPUT); // IN1 of motor A
pinMode(motorAPin2, OUTPUT); // IN2 of motor A
pinMode(motorBPin1, OUTPUT); // IN3 of motor B
pinMode(motorBPin2, OUTPUT); // IN4 of motor B
pinMode(motorASpeedPin, OUTPUT); // Speed of motor A
pinMode(motorBSpeedPin, OUTPUT); // Speed of Motor B
}

void loop()

{ x=AccelerometerSensor.getX();
y=AccelerometerSensor.getY();
z=AccelerometerSensor.getZ();

/* If up is pressed, move the car forward. */


if (GamePad.isUpPressed()|| y < -5)
{
analogWrite(motorASpeedPin, 255);
analogWrite(motorBSpeedPin, 255);
digitalWrite(motorAPin1, LOW);
digitalWrite(motorAPin2, HIGH);
digitalWrite(motorBPin1, LOW);
digitalWrite(motorBPin2, HIGH);
digitalWrite(ledPin, HIGH);

}
/* If down is pressed, move the car backwards. */
else if (GamePad.isDownPressed()|| y > 6)
{
analogWrite(motorASpeedPin, 255);
analogWrite(motorBSpeedPin, 255);
digitalWrite(motorAPin1, HIGH);
digitalWrite(motorAPin2, LOW);
digitalWrite(motorBPin1, HIGH);
digitalWrite(motorBPin2, LOW);
digitalWrite(ledPin, HIGH);

}
/* If right is pressed, turn the car to the right. */
else if (GamePad.isRightPressed() || x < -6)
{
analogWrite(motorASpeedPin, 255);
analogWrite(motorBSpeedPin, 255);
digitalWrite(motorAPin1, LOW);
digitalWrite(motorAPin2, HIGH);
digitalWrite(motorBPin1, HIGH);
digitalWrite(motorBPin2, LOW);
digitalWrite(ledPin, HIGH);

}
/* If left is pressed, turn the car to the left. */
else if (GamePad.isLeftPressed()|| x > 6)
{
analogWrite(motorASpeedPin, 255);
analogWrite(motorBSpeedPin, 255);
digitalWrite(motorAPin1, HIGH);
digitalWrite(motorAPin2, LOW);
digitalWrite(motorBPin1, LOW);
digitalWrite(motorBPin2, HIGH);
digitalWrite(ledPin, HIGH);

}
/* If nothing is pressed stop all motors. */
else
{
analogWrite(motorASpeedPin, 0);
analogWrite(motorBSpeedPin, 0);
digitalWrite(ledPin, LOW);
}

}
4) Arduino Automatic Room Light Controller with Bidirectional
Visitor
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Relay (generic)
× 1

Resistor 100 ohm

× 1

Infrared Module
× 1
Adafruit Standard LCD - 16x2
White on Blue × 1

General Purpose Transistor NPN

× 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

The project of “Digital visitor counter” is based on the interfacing of


some components such as sensors, motors etc. with Arduino
microcontroller. This counter can count people in both directions. This
circuit can be used to count the number of persons entering a
hall/mall/home/office in the entrance gate and it can count the number
of persons leaving the hall by decrementing the count at the same gate
or an exit gate, and that depends upon sensor placement in the
mall/hall. It can also be used at gates of parking areas and other public
places.
This project is divided into four parts: sensors, controller, counter
display and gate. The sensor would observe an interruption and provide
an input to the controller which would run the counter increment or
decrement depending on the entering or exiting of people. And
counting is displayed on a 16x2 LCD through the controller.

SCHEMATICS
CODE
#include<LiquidCrystal.h>
LiquidCrystal lcd(13,12,11,10,9,8);
#define in 14
#define out 19
#define relay 2
int count=0;
void IN()
{
count++;
if(count>=10)
{
count=10;
}
lcd.clear();
lcd.print("Person In Room:");
lcd.setCursor(0,1);
lcd.print(count);
delay(1000);
}
void OUT()
{
count--;
if(count<=0)
{
count=0;
}
lcd.clear();
lcd.print("Person In Room:");
lcd.setCursor(0,1);
lcd.print(count);
delay(1000);
}
void setup()
{
lcd.begin(16,2);
lcd.print("Visitor Counter");
delay(2000);
pinMode(in, INPUT);
pinMode(out, INPUT);
pinMode(relay, OUTPUT);
lcd.clear();
lcd.print("Person In Room:");
lcd.setCursor(0,1);
lcd.print(count);
}
void loop()
{

if(digitalRead(in))
IN();
if(digitalRead(out))
OUT();

if(count<=0)
{
lcd.clear();
digitalWrite(relay, LOW);
lcd.clear();
lcd.print("Nobody In Room");
lcd.setCursor(0,1);
lcd.print("Light Is Off");
delay(200);
}

else
digitalWrite(relay, HIGH);

}
5) Arduino a Neonate Incubator Approach

COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

ABOUT THIS PROJECT


This project is an aproach to understand how neonate incubator works.
!!WARNING!! IT IS NOT SUPOUSED TO TAKE CARE OF ANY
KIND OF LIFE, the purpose here is to understand the basics and get
your project as better as possible, and of course have fun with it!!
This was made to represent the idea of low cost medical devices for a
diploma work.
The main goal of this incubator is to mantain the temperature between
a max and min temperature range, this temperature range can be
managed with a 5-button control. The airflow is created with help of
two fans that keep air flowing (two fans works at small velocity but
one of them has an increased velocity switch in case of overwarming
airflow), a ceramic warmer, a servo motor to open and close a gate that
lets overwarmed air to flow outside the system, temperature and
humidity sensors, a power supply and of course, our good Arduino
Nano.

An upside view of the system


Here is the ceramic warmer, some sensors and the servo controlled gate

Here you can see the place in which the air is warmed, a Lm35
temperature sensor is in the top of the box
This project will be divided in several small projects in order to explain
how to build each specific part that need special attention as the power
controller and the button controller.

SCHEMATICS

Simplified diagram
This diagram content the following:
1. 220V cable
2. Power source 220v to 24V @ 4A
3. Arduino Nano
4. I2C 20x4 LCD
5. Power controller for fans and warmer
6. 5-button control
7. Ceramic warmer
8. Lm 35 temperature sensor
9. DHT22 humidity and temperature sensor
10. 12V computer fan
11. Small servo motor.
12. Big plastic box
Arduino diagram
The Arduino connections to peripherals.
Power management
The two independent lines were made experimentally to check if the
helped to avoid some noises, but they did not :) So you can use just
one.

Amplification stages and voltage follower


Voltage follower is used to have better signal from thermistors and the
OpAmps to expand the Lm35 readable range in Arduino
5-button module
Here is a simple 5-button controller
Power control of fans and ceramic warmer
CODE

#include <LCD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SimpleDHT.h>
#include "RTClib.h"
#include <dht.h>
#include <Servo.h>

Servo myservo;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //Set the LCD I2C address

//Digitals
const int pin1DHT22 = 2; //Sensor humedad 1
const int Warmer = 3; //Relay 3
const int Fan_1 = 6; //Relay 6 // Fan High
const int buzzer = 4; //Piezo sounder
const int button1 = 9;
const int button2 = 10;
const int button3 = 11;
const int button4 = 12;
const int button5 = 13;

//Analogs
const int inPinTh_1 = A1; //Termistor 2
const int tempPin_1 = A2; //lm35_1
const int tempPin_2 = A3; //lm35_2

SimpleDHT22 dht22_1;
RTC_DS1307 RTC;

int temp_1, temp_2, DHT22Temp_1;


int errorSense_1, errorSense_2, count_1, count_2, count_3 = 0;

int menuScreen, menuScreenUseAlarm, menuScreenMode, menuScreenTempAlarm,


menuScreenTemp, menuScreenHumid, mode, modeAlarm, manualSettings = 0;
bool back, next, select, up, down = 0;

float Temp1_Neonate, Temp2_Neonate, averageTemp_Neonate, lm35_1, lm35_2,


coefWarmer, midleRangeTemp = 0;
int pursuedHigherT = 373;
int pursuedLowerT = 365;

float upperTemp = 35;


float lowerTemp = 34;
float lowerTempComp = 0;

float upperTempAlarm = 37.5;


float lowerTempAlarm = 36.5;
float lowerTempCompAlarm = 0;

unsigned long currentMillis;


unsigned long previousMillis = 0; // last time update
long interval = 1000; // interval at which to do something (milliseconds)

unsigned long currentMillis_1;


unsigned long previousMillis_1 = 0; // last time update
long interval_1 = 2000; // interval at which to do something (milliseconds)

void setup()
{
myservo.attach(1);
myservo.write(122); //Para flujo sobrecalentado
delay(250);
myservo.write(70); //Flujo normal
delay(250);
myservo.write(122);
delay(250);
myservo.write(70);
Wire.begin();
RTC.begin();
pinMode(Fan_1, OUTPUT);
pinMode(Warmer, OUTPUT);
pinMode(back, INPUT);
pinMode(next, INPUT);
pinMode(select, INPUT);
pinMode(up, INPUT);
pinMode(down, INPUT);

pinMode(buzzer, OUTPUT);
digitalWrite(buzzer, LOW);

digitalWrite(Fan_1, LOW);
digitalWrite(Warmer, LOW);

lcd.begin(20, 4); // initialize the lcd for 20 chars 4 lines and turn on backlight
lcd.backlight();
menuScreen_0();
menuScreen_1();
RTC.adjust(DateTime(__DATE__, __TIME__));
// Check to see if the RTC is keeping time. If it is, load the time from your computer.
if (! RTC.isrunning()) {
lcd.print("Change clock battery");
// This will reflect the time that your sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
}

void loop()
{
currentMillis = millis();
buttonState();

switch (menuScreen) {
case 0:
menuScreen_UseAlarm();
break;
case 1:
menuScreen_SetAlarm();
break;
case 2:
menuScreen_Mode();
break;
case 3:
Screen_Auto_intro();
break;
case 4:
menuScreen_Temp();
break;
case 5:
Alarms();
currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
Screen_Auto();
}
break;
case 6:
Alarms();
currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
Screen_Manual();
}
break;
}

void mainScreen()
{
currentMillis_1 = millis();

lcd.setCursor(0, 0);
lcd.print("Baby T "); lcd.print(averageTemp(), 1); lcd.print((char)223); //lcd.print("C");
lcd.setCursor(13, 0);
lcd.print("WarmerT");
lcd.setCursor(0, 1);
lcd.print("Case T "); lcd.print(templm35_1(), 1); lcd.print((char)223); // Temp case lm35 1
lcd.setCursor(14, 1);
lcd.print(templm35_2(), 1); lcd.print((char)223); // Temp warmer lm35 2
lcd.setCursor(0, 2);
lcd.print("Cham T ");
if (currentMillis_1 - previousMillis_1 > interval_1) { // Importante para dar ciclo de espera
a los sensores de humidificacion
previousMillis_1 = currentMillis_1; lcd.print(DHT22TempRead_1(), 1);
lcd.print((char)223);
}
lcd.setCursor(0, 3);
lcd.print("Man. mode");
RelojParaPantallaSerial();

void RelojParaPantallaSerial()
{
DateTime now = RTC.now();
lcd.setCursor(12, 3);
if (now.hour() < 10 ) {
lcd.print("0");
lcd.print(now.hour(), DEC);
}
else {
lcd.print(now.hour(), DEC);
}
lcd.print(':');
if (now.minute() < 10) {
lcd.print("0");
lcd.print(now.minute(), DEC);
}
else {
lcd.print(now.minute(), DEC);
}
lcd.print(':');
if (now.second() < 10) {
lcd.print("0");
lcd.print(now.second());
}
else {
lcd.print(now.second(), DEC);
}
}

void DHT22Sensor_1() // DHT22 sampling rate is 0.5HZ.


{
count_1 ++;
if (count_1 > 1) { //Sets counting of 2 seconds
count_1 = 0;
byte temperature_1 = 0;
byte humidity_1 = 0;
int err_1 = dht22_1.read(pin1DHT22, &temperature_1, &humidity_1, NULL);
if (err_1 != SimpleDHTErrSuccess) {
errorSense_1 ++;
if (errorSense_1 > 2) { // Here we set the number of errors allowed untill display an
error
lcd.setCursor(10, 2);
lcd.print("Error"); lcd.print(err_1); delay(1000);
return;
}
return;
}
errorSense_1 = 0; // Reset the counter if the errors in a row are not higher than
errors allowed untill display an error
DHT22Temp_1 = ((int)temperature_1);
count_1 = 0;
}
}

int DHT22TempRead_1()
{
DHT22Sensor_1();
return DHT22Temp_1;
}

float temperature_Neonate() // CREAR ERROR DE TEMP


{
float val1 = 0;
for (int i = 0; i < 5; i++) {
val1 = val1 + analogRead(inPinTh_1);
delay(2);
}
Temp2_Neonate = val1 / 5;
return Temp2_Neonate;
}

float templm35_1()
{
float val2 = 0;
for (int i = 0; i < 5; i++) {
val2 = val2 + analogRead(tempPin_1);
delay(2);
}
lm35_1 = val2 / 5;
lm35_1 = mapf(lm35_1, 284.5, 323, 30, 37);
return lm35_1;
}

float templm35_2()
{
float val3 = 0;
for (int i = 0; i < 5; i++) {
val3 = val3 + analogRead(tempPin_2);
delay(2);
}
lm35_2 = val3 / 5;
lm35_2 = mapf(lm35_2, 284.5, 323, 30, 37);
return lm35_2;
}

double mapf(double x, double in_min, double in_max, double out_min, double out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

float averageTemp() // Average was with two thermometers


{
averageTemp_Neonate = temperature_Neonate();
averageTemp_Neonate = mapf(averageTemp_Neonate, 284.5, 323, 30, 37);
return averageTemp_Neonate;
}

int int_templm35_1()
{
int intlm35_1 = templm35_1();
return intlm35_1;
}

int int_tempcase()
{
int int_templm35_1_0 = templm35_1() * 10;
return int_templm35_1_0;
}

int int_templm35_2()
{
int intlm35_2 = templm35_2();
return intlm35_2;
}

int int_templm35_2_0()
{
int int_templm35_2_0 = templm35_2() * 10;
return int_templm35_2_0;
}

////////////////////////////////////////////////////

void menuScreen_0 ()
{
lcd.setCursor(0, 1);
lcd.print(" The Baby Warmer.");
delay(1000);
lcd.setCursor(0, 3);
lcd.print("Welcome!");
delay(500);
lcd.setCursor(15, 3);
lcd.print("V 1.3");
delay(1000);
lcd.clear();
}

void menuScreen_1()
{
lcd.setCursor(0, 0);
lcd.print("The following menu");
lcd.setCursor(0, 1);
lcd.print("will help you to set");
lcd.setCursor(0, 2);
lcd.print("the incubator system");
delay(3000);
lcd.clear();
}

void menuScreen_UseAlarm()
{
switch (menuScreenUseAlarm) {
case 0:
lcd.setCursor(0, 0);
lcd.print("Activate neonate");
lcd.setCursor(0, 1);
lcd.print("temp. alarm?");
if (modeAlarm == 0) {
lcd.setCursor(0, 2);
lcd.print("->");
}
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() <= 320) {
upperTempAlarm = 32;
lcd.setCursor(10, 1);
lcd.print("MIN RANGE");
delay(1000);
lcd.setCursor(9, 1);
lcd.print(" ");
return;
}
upperTempAlarm = upperTempAlarm - 0.1;
lcd.setCursor(3, 1);
lcd.print(upperTempAlarm, 1);
down = 0;
}
break;

case 1:
lcd.setCursor(0, 0);
lcd.print("Set the lower range");
lcd.setCursor(0, 1);
lcd.print("T=");
lcd.setCursor(3, 1);
lcd.print(lowerTempAlarm, 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) {
menuScreenTempAlarm = 0;
lcd.clear();
delay(200);
back = 0;
}
else if (next) {
menuScreenTempAlarm = 2;
next = 0;
lcd.clear();
delay(500);
}
else if (select) {
menuScreenTempAlarm = 2;
select = 0;
lcd.clear();
delay(500);
}
else if (up) {
if (int_lowerTempAlarm() >= (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() <= 280) {
lowerTempAlarm = 28;
lcd.setCursor(10, 1);
lcd.print("MIN TEMP");
delay(1000);
lcd.setCursor(9, 1);
lcd.print(" ");
return;
}
lowerTempAlarm = lowerTempAlarm - 0.1;
lcd.setCursor(3, 1);
lcd.print(lowerTempAlarm, 1);
down = 0;
}
break;

case 2:
lcd.setCursor(0, 0);
lcd.print("Upper limit: ");
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("Lower limit:");
lcd.setCursor(0, 3);
lcd.print("T=");
lcd.setCursor(3, 3);
lcd.print(lowerTempAlarm, 1);
lcd.print((char)223);
lcd.print("C");
lcd.setCursor(9, 3);
lcd.print(" Continue?");
if (back) {
menuScreenTempAlarm = 1;
lcd.clear();
delay(200);
back = 0;
}
else if (next) {
menuScreen = 2;
next = 0;
lcd.clear();
delay(500);
}
else if (select) {
menuScreen = 2;
select = 0;
lcd.clear();
delay(500);
}
else if (up) {
up = 0;
}
else if (down) {
down = 0;
}
}

void menuScreen_Mode()
{
switch (menuScreenMode) {
case 0:
lcd.setCursor(0, 0);
lcd.print("Select the mode:");

if (mode == 0) {
lcd.setCursor(0, 2);
lcd.print("->");
}
else if (mode == 1) {
lcd.setCursor(0, 3);
lcd.print("->");
}
lcd.setCursor(2, 2);
lcd.print("Skin mode aut.");
lcd.setCursor(2, 3);
lcd.print("Temp setting man.");
if (back) {
back = 0;
lcd.clear();
delay(500);
menuScreenTempAlarm = 0;
menuScreen = 0;
}
else if (next) {
if (mode == 0) {
menuScreen = 3;
}
else if (mode == 1) {
menuScreen = 4;
}
lcd.clear();
delay(500);
next = 0;
}
else if (select) {
if (mode == 0) {
menuScreen = 3;
}
else if (mode == 1) {
menuScreen = 4;
}
lcd.clear();
delay(500);
select = 0;
}
else if (up) {
mode = mode - 1;
if (mode < 0) {
mode = 1;
}
delay(100);
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print(" ");
up = 0;
}
else if (down) {
mode = mode + 1;
if (mode > 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() <= 310) {
upperTemp = 31;
lcd.setCursor(10, 1);
lcd.print("MIN RANGE");
delay(1000);
lcd.setCursor(9, 1);
lcd.print(" ");
return;
}
upperTemp = upperTemp - 0.1;
lcd.setCursor(3, 1);
lcd.print(upperTemp, 1);
down = 0;
}
break;

case 1:
lcd.setCursor(0, 0);
lcd.print("Set the lower range");
lcd.setCursor(0, 1);
lcd.print("T=");
lcd.setCursor(3, 1);
lcd.print(lowerTemp, 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) {
menuScreenTemp = 0;
lcd.clear();
delay(200);
back = 0;
}
else if (next) {
menuScreenTemp = 2;
next = 0;
lcd.clear();
delay(500);
}
else if (select) {
menuScreenTemp = 2;
select = 0;
lcd.clear();
delay(500);
}
else if (up) {
if (int_lowerTemp() >= (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() <= 300) {
lowerTemp = 30;
lcd.setCursor(10, 1);
lcd.print("MIN TEMP");
delay(1000);
lcd.setCursor(9, 1);
lcd.print(" ");
return;
}
lowerTemp = lowerTemp - 0.1;
lcd.setCursor(3, 1);
lcd.print(lowerTemp, 1);
down = 0;
}
break;

case 2:
lcd.setCursor(0, 0);
lcd.print("Upper limit: ");
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("Lower limit:");
lcd.setCursor(0, 3);
lcd.print("T=");
lcd.setCursor(3, 3);
lcd.print(lowerTemp, 1);
lcd.print((char)223);
lcd.print("C");
lcd.setCursor(9, 3);
lcd.print(" Continue?");
if (back) {
menuScreenTemp = 1;
lcd.clear();
delay(200);
back = 0;
}
else if (next) {
menuScreen = 6;
next = 0;
lcd.clear();
delay(500);
}
else if (select) {
menuScreen = 6;
select = 0;
lcd.clear();
delay(500);
}
else if (up) {
up = 0;
}
else if (down) {
down = 0;
}
}

void Screen_Auto() {
Screen_Auto_S();
warmerParameters_Auto();
}
void Screen_Auto_S()
{
currentMillis_1 = millis();

lcd.setCursor(0, 0);
lcd.print("Baby T "); lcd.print(averageTemp(), 1); lcd.print((char)223); //lcd.print("C");
lcd.setCursor(13, 0);
lcd.print("WarmerT");
lcd.setCursor(0, 1);
lcd.print("Case T "); lcd.print(templm35_1(), 1); lcd.print((char)223); // Temp case lm35 1
lcd.setCursor(14, 1);
lcd.print(templm35_2(), 1); lcd.print((char)223); // Temp warmer lm35 2
lcd.setCursor(0, 2);
lcd.print("Purs Baby T ");
lcd.print("37.3"); lcd.print((char)223);
lcd.setCursor(0, 3);
lcd.print("Aut. mode");
RelojParaPantallaSerial();

void Screen_Manual()
{
mainScreen();
warmerParameters_Manual();
}

void warmerParameters_Auto()
{
switch (manualSettings) {
case 0:
if (int_tempcase() <= int_lowerTemp()) {
digitalWrite(Warmer, HIGH);
}
else if (int_tempcase() > int_lowerTemp()) {
manualSettings++;
digitalWrite(Warmer, LOW);
}

case 1:
if (int_tempcase() <= pursuedLowerT) {
digitalWrite(Warmer, HIGH);
delay(400);
digitalWrite(Warmer, LOW);
delay(300);
}
else if (int_tempcase() >= pursuedHigherT) {
digitalWrite(Warmer, LOW);
digitalWrite(Fan_1, HIGH);
myservo.write(122); //Para flujo sobrecalentado
delay(2500); //Variable de tiempo de enfriamiento, a
mas tiempo, mas frio
digitalWrite(Fan_1, LOW);
myservo.write(70);
delay(1000);
}
}
}

void warmerParameters_Manual()
{
switch (manualSettings) {
case 0:
if (int_tempcase() <= int_lowerTemp()) {
digitalWrite(Warmer, HIGH);

}
else if (int_tempcase() > int_lowerTemp()) {
manualSettings++;
digitalWrite(Warmer, LOW);
}

case 1:
if (int_tempcase() <= int_upperTemp()) {
digitalWrite(Warmer, HIGH);
delay(400);
digitalWrite(Warmer, LOW);
delay(300);
}
else if (int_tempcase() >= int_upperTemp()) {
digitalWrite(Warmer, LOW);
digitalWrite(Fan_1, HIGH);
myservo.write(122); //Para flujo sobrecalentado
delay(2500); //Variable de tiempo de enfriamiento, a
mas tiempo, mas frio
digitalWrite(Fan_1, LOW);
myservo.write(70);
delay(1000);
}
}
}

void Alarms()
{
if (modeAlarm == 1)
{
if (averageTemp() < lowerTempAlarm || averageTemp() > 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
× 1
not have to be UNO

DC-DC 1.5-3V to 300-400V 380V


High Voltage Boost Step-up
Voltage Inverter Module
Ideal final voltage is 400V, but × 1
can be from 350-450V (the power
range of the GM tube).

STS-5 Geiger Muller Tube


I found mine on ebay (less
expensive). Be aware that you will
× 1
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 × 1
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 self-
assembled 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 <LiquidCrystal_I2C.h>
#include <Wire.h>

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<currentCPM+1;x++) {
averageCPM = averageCPM + CPMArray[x];
}
averageCPM = averageCPM / (currentCPM + 1);
for (int x=0;x<currentCPM+1;x++) {
sdCPM = sdCPM + sq(CPMArray[x] - averageCPM);
}
sdCPM = sqrt(sdCPM / currentCPM) / sqrt(currentCPM+1);

Serial.println("Avg: " + String(averageCPM) + " +/- " + String(sdCPM) + " ArrayVal: " +
String(CPMArray[currentCPM]));
currentCPM = currentCPM + 1;
displayAverageCPM();
}
}

void impulse() {
counts++;
}
void displayAverageCPM() {
lcd.setCursor(0,1);
lcd.print("Avg: ");
lcd.print(outputSieverts(averageCPM));
lcd.print("+/-");
lcd.print(outputSieverts(sdCPM));
}
float outputSieverts(float x) {
float y = x * 0.0057;
return y;
}
7) Arduino WKR1000 Weather Station

COMPONENTS AND SUPPLIES


Arduino MKR1000
× 1

Adafruit TSL2561 Luminosity


Sensor × 1

Adafruit BMP180 Barometric


Pressure/Temperature × 1

OLED display I2C


× 1

SparkFun Level Shifter Board

× 1

Sharp GP2Y1010AU0F
× 1

Soil Moisture Sensor


× 1

Breadboard (generic)

× 1

Jumper wires (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

myDevices Cayenne

ABOUT THIS PROJECT


The OLED display shows the temperature, pressure and dust. The Arduino
MKR1000 is connected to the Cayenne over MQTT.
Connecting the Arduino MKR1000 to Cayenne:
Add new: Device/Widget
Bring Your Own Thing
Add code to Username, Password and Client ID
Add code to SSID and Password from your Wi-Fi
Upload code to the Arduino MKR1000
Wait for board to connect
Add Widgets:
Add new: Device/Widget
Custom Widgets
Select a widget that you need
Enter the name of the widget
Select device, Virtual Pin, Pin number
Select Data, Unit, Icon
Add Widget
SCHEMATICS
CODE
#define CAYENNE_PRINT Serial // Comment this out to disable prints and save space
#include <CayenneMQTTMKR1000.h>

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_BMP085_U.h>
#include <Adafruit_TSL2561_U.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define BAROMETER_PIN V1
#define TEMPERATURE_PIN V2
#define LIGHT_PIN V3
#define DUST_PIN V4
#define MOISTURE_PIN V5

float temperature;
float pressure;
float voltage;
int moisture;

int measuringPin = A1;


int ledPin = 2;
const int timeMeasuring = 280;
const int timeStabilization = 40;
const int timeSleep = 9680;
float voltageAnalog = 0;
float voltageConversion = 0;
float dustiness = 0;

Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10180);


const int address = TSL2561_ADDR_FLOAT;
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(address, 12345);

// WiFi network info.


char ssid[] = "SSID";
char wifiPassword[] = "Password";

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "Username";
char password[] = "Password";
char clientID[] = "ClientID";
unsigned long lastMillis = 0;

void setup()
{
Serial.begin(9600);
Cayenne.begin(username, password, clientID, ssid, wifiPassword);
pinMode(ledPin,OUTPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
if (!bmp.begin())
{
CAYENNE_LOG("No BMP sensor detected");
while (1);
}
if (!tsl.begin())
{
CAYENNE_LOG("No TSL2561 detected");
while (1);
}

tsl.enableAutoRange(true);
/* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); /* fast but low
resolution */
// tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); /* medium resolution
and speed */
// tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); /* 16-bit data but
slowest conversions */
}

void loop()
{
Cayenne.loop();

//Publish data every 10 seconds (10000 milliseconds). Change this value to publish at a
different interval.
if (millis() - lastMillis > 10000) {
lastMillis = millis();
//Write data to Cayenne here. This example just sends the current uptime in milliseconds.
Cayenne.virtualWrite(0, lastMillis);

sensors_event_t event;
tsl.getEvent(&event);
bmp.getPressure(&pressure);
bmp.getTemperature(&temperature);

digitalWrite(ledPin,LOW);
delayMicroseconds(timeMeasuring);
voltageAnalog = analogRead(measuringPin);
delayMicroseconds(timeStabilization);
digitalWrite(ledPin,HIGH);
delayMicroseconds(timeSleep);

voltageConversion = voltageAnalog * 2 * (3,3 / 1024.0);


dustiness = (0.17 * voltageConversion - 0.1)*1000;

moisture = analogRead(A2);

Cayenne.luxWrite(LIGHT_PIN, event.light);
Cayenne.hectoPascalWrite(BAROMETER_PIN, pressure);
Cayenne.celsiusWrite(TEMPERATURE_PIN, temperature);
Cayenne.virtualWrite(DUST_PIN, dustiness);
Cayenne.virtualWrite(MOISTURE_PIN, map(moisture, 1023, 0, 0, 100));

}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(temperature);
display.setCursor(40, 0);
display.println("C");
display.setCursor(0, 10);
display.println(pressure);
display.setCursor(55, 10);
display.println("Pa");
display.setCursor(0, 20);
display.println(dustiness);
display.setCursor(45, 20);
display.println("ug/m3");
display.display();

}
8) Arduino Due TIC TAC TOE with Touchscreen

COMPONENTS AND SUPPLIES


Arduino Due

× 1

2,8 zoll TFT LCD with


touchscreen × 1
Jumper wires (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

About
Hello, I want to share my work on the project from
nickthegreek82: arduino-touch-tic-tac-toe-game.
You need:
the Adafruit Library
the GFX Library
and the URTouch Library
Wiring
The wiring is as following for the touch-screen:
Touch -> 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 <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <URTouch.h>

#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<7;i++)
{
tft.drawLine(60,y+i,270,y+i,WHITE);
}
}

void drawVerticalLine(int x)
{
int i=0;
for(i=0;i<7;i++)
{
tft.drawLine(x+i,20,x+i,220,WHITE);
}
}
void drawStartScreen()
{
tft.fillScreen(BLACK);

//Draw white frame


tft.drawRect(0,0,319,240,WHITE);

//Print "Tic Tac Toe" Text


tft.setCursor(30,100);
tft.setTextColor(WHITE);
tft.setTextSize(4);
tft.print("Tic Tac Toe");

//Print "YouTube!" text


tft.setCursor(80,30);
tft.setTextColor(GREEN);
tft.setTextSize(4);
tft.print("Arduino");

buttons[0].initButton(&tft, 160,200,200,40,WHITE, RED, WHITE, start, 2);


buttons[0].drawButton();
}

void drawCircle(int x, int y)


{
drawBitmap(x,y,circle,65,65,RED);
}

void drawX(int x, int y)


{
drawBitmap(x,y,x_bitmap,65,65,BLUE);
}
void drawBitmap(int16_t x, int16_t y,
const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) {

int16_t i, j, byteWidth = (w + 7) / 8;
uint8_t byte;

for(j=0; j<h; j++) {


for(i=0; i<w; i++) {
if(i & 7) byte <<= 1;
else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8);
if(byte & 0x80) tft.drawPixel(x+i, y+j, color);
}
}
}
void computerMove(int board[9]) {
int move = -1;
int score = -2;
int i;
for(i = 0; i < 9; ++i) {
if(board[i] == 0) {
board[i] = 1;
int tempScore = -minimax(board, -1, 0);
board[i] = 0;
if(tempScore > score) {
score = tempScore;
move = i;
}
}
}
//returns a score based on minimax tree at a given node.
board[move] = 1;
drawCpuMove(move);
delay(100);
}
void playerMove(int board[9]) {
int move = 0;
b = 1;
do{
if (myTouch.dataAvailable() == true)
{
myTouch.read();
x = myTouch.getX(); //Get touch point
y = myTouch.getY();

if((x>55 && x<125)&& (y>0 && y<80)) //0


{
if(board[0]==0)
{
move=0;
b=0;
}
}
else if((x>125 && x<195) && (y>0 && y<80)) //1
{

if(board[1]==0)
{
move=1;
b=0;
}
}
else if((x>195&&x<265)&& (y>0 && y<80)) //2
{
if(board[2]==0)
{
move=2;
b=0;
}
}

else if((x>55 && x<125)&& (y>80 && y<155)) //3


{
if(board[3]==0)
{
move=3;
b=0;
}
}
else if((x>125 && x<195)&& (y>80 && y<155)) //4
{
if(board[4]==0)
{
move=4;
b=0;
}
}

else if((x>195&&x<265)&& (y>80 && y<155)) //5


{
if(board[5]==0)
{
move=5;
b=0;
}
}

else if((x>55 && x<125)&& (y>155 && y<235)) //6


{
if(board[6]==0)
{
move=6;
b=0;
}
}

else if((x>125 && x<195)&& (y>155 && y<235)) //7


{
if(board[7]==0)
{
move=7;
b=0;
}
}

else if((x>195&&x<265)&& (y>155 && y<235)) //8


{
if(board[8]==0)
{
move=8;
b=0;
}
}

}
}while(b);
board[move] = -1;
drawPlayerMove(move);
delay(100);
}
int win(const int board[9]) {
//list of possible winning positions
unsigned wins[8][3] = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
int winPos;
for(winPos = 0; winPos < 8; ++winPos) {
if(board[wins[winPos][0]] != 0 && board[wins[winPos][0]] == board[wins[winPos][1]]
&& board[wins[winPos][0]] == board[wins[winPos][2]])
return board[wins[winPos][2]];
}
return 0;
}

int minimax(int board[9], int player, int depth) {


//check the positions for players
int winner = win(board);
if(winner != 0) return winner*player;

int move = -1;


int score = -2;
int i;
for(i = 0; i < 9; ++i) {

if(board[i] == 0) {
board[i] = player;
int thisScore=0;
if (depth<difficulty){
thisScore = -minimax(board, player*-1,depth+1);
}

if(thisScore > score) {


score = thisScore;
move = i;
}
//choose the worst move for opponent
board[i] = 0;
}
}
if(move == -1) return 0;
return score;
}
void drawCpuMove(int move)
{
switch(move)
{
case 0: drawCircle(55,15); break;
case 1: drawCircle(130,15); break;
case 2: drawCircle(205,15); break;
case 3: drawCircle(55,85); break;
case 4: drawCircle(130,85); break;
case 5: drawCircle(205,85); break;
case 6: drawCircle(55,155); break;
case 7: drawCircle(130,155);break;
case 8: drawCircle(205,155);break;
}
}

void drawPlayerMove(int move)


{
switch(move)
{
case 0: drawX(55,15); break;
case 1: drawX(130,15); break;
case 2: drawX(205,15); break;
case 3: drawX(55,85); break;
case 4: drawX(130,85); break;
case 5: drawX(205,85); break;
case 6: drawX(55,155); break;
case 7: drawX(130,155);break;
case 8: drawX(205,155);break;
}
}

9) Oled Display with Arduino 101


COMPONENTS AND SUPPLIES

Arduino 101 & Genuino 101

× 1

OLED 128X64
× 1

Rotary potentiometer (generic)


× 1

Jumper wires (generic)

× 1

USB-A to B Cable

× 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Months ago I bought my Arduino 101 and wanted to connect my shields


and modules that I used in Arduino One, but there were always problems
with the libraries and there were many headaches. I was looking for
information on the internet and could not find my answers.
Today I finally found the way to connect my OLED screen of 0.96 inches
with Arduino 101 and I want to share my discovery with this tutorial,
since it could help many people with the same problem as me.
Materials
To do this tutorial, we need materials, in this case we will use an Arduino
101, the OLED screen with the model SSD1306 of resolution 128X64
pixels, cables, a potentiometer and a protoboard.

Code
Then open Arduino IDE and copy and paste the next code:
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*
clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All
Boards without Reset of the Display
int a=0; //variable of value of analog read pin
char taco[4];//variable to send text to the oled display
void setup(void) {
u8g2.begin();// Oled display begins
}
void loop(void) {
a=analogRead(A0); //read potentiometer value
sprintf(taco,"%04d",a); //convert potentiometer value to string
u8g2.clearBuffer(); // clear the internal memory
u8g2.setFont(u8g2_font_inr38_mf); // choose a suitable font
u8g2.drawStr(0,60,taco); // write something to the internal memory
u8g2.sendBuffer(); // transfer internal memory to the display
delay(1000);
For everything to work we must download the library u8g2.

After uploading the code, and having connected the potentiometer to the
Arduino plate, the value of the potentiometer can be seen in the display,
from 0 to 1023, as shown below.
SCHEMATICS
CODE

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /*


data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display

int a=0; //variable of value of analog read pin


char taco[4];//variable to send text to the oled display
void setup(void) {
u8g2.begin();// Oled display begins
}

void loop(void) {
a=analogRead(A0); //read potentiometer value
sprintf(taco,"%04d",a); //convert potentiometer value to string
u8g2.clearBuffer(); // clear the internal memory
u8g2.setFont(u8g2_font_inr38_mf); // choose a suitable font
u8g2.drawStr(0,60,taco); // write something to the internal memory
u8g2.sendBuffer(); // transfer internal memory to the
display
delay(1000);
}

10) Arduino Ask the Magic 8 Ball


COMPONENTS AND SUPPLIES

Resistor 10k ohm

× 2

Resistor 221 ohm

× 2

SparkFun Pushbutton switch


12mm
× 1

Rotary potentiometer (generic)

× 1

Arduino LCD Screen

× 1

Jumper wires (generic)

× 21

Arduino UNO & Genuino UNO

× 1

Breadboard (generic)

× 1

USB-A to Micro-USB Cable

× 1
NECESSARY TOOLS AND MACHINES
Arduino Materia 101
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

The purpose of this project was to create a Magic 8 Ball - Arduino


style. We were able to do so by modifying the Crystal Ball project in
the Arduino starter kit. The goal was to create a micro controller that
generates 20 random responses to the user's statement and then
switches to another response when a switch button is pressed.
Why
Magic 8 Balls are one of the many fortune telling toys that are popular
with children. It was originally developed in 1950. It returns 20
different statements like "It is certain" in response to questions that
individuals ask. Magic 8 Balls are unique because can be used by
anyone, not just a fortune teller.
How It Works
The LCD display originally shows "Ask the Magic 8 ball!". The user
then asks a question and presses the button switch. The display then
shifts to one of the 20 responses and then displays "Ask another
question!". The user can continue pressing the switch until all of their
questions are answered.
How to Make It
Follow the Arduino Project 11 - Crystal Ball in the Arduino starter kit
in order to construct the initial circuit. Replace the tilt sensor with a
button switch and add a 220 ohm resistor two spaces in front of the
button switch. Alter the code so that when the button is pressed, the
Magic 8 ball returns one of the 20 responses and then displays "Ask
another question!". This alteration includes removing the code about
the tilt sensor and replacing it with an if statement (if the switch is
being pressed then return the statement + "Ask another question!").
Change the code to reflect what you want the magic 8 ball's response to
be. During this step you can utilize the delay function to keep a
message on the LCD display for a certain amount of time. In between
each of the 20 cases make sure to include a break to differentiate
between each case.

SCHEMATICS
CODE
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int switchPin = 6;
int switchState = 0;
//declaring the variable for the switch
int reply;
void setup() {
pinMode(0, INPUT);
//power source for switch
lcd.begin(16, 2);
pinMode(switchPin, INPUT);
lcd.print("Ask the Magic");
lcd.setCursor(0,1);
lcd.print("8 ball!");
//welcome message
}
void loop(){
switchState = digitalRead(switchPin);
{
if(switchState == HIGH){
//when the switch is pressed
reply = random(8);
//return a random case
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("");
lcd.setCursor(0,1);
switch(reply){
case 0:
lcd.begin(16, 2);
lcd.print("It is");
lcd.setCursor(0,1);
lcd.print("certain :)");
delay (2500);
//maintain the first message
lcd.clear();
//clear the first message
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
//print the second message
break;
//next case
case 1:
lcd.begin(16, 2);
lcd.print("As I see it,");
lcd.setCursor(0,1);
lcd.print("yes :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 2:
lcd.begin(16, 2);
lcd.print("Reply hazy");
lcd.setCursor(0,1);
lcd.print("try again :/");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 3:
lcd.begin(16, 2);
lcd.print("Don't count");
lcd.setCursor(0,1);
lcd.print("on it :(");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 4:
lcd.begin(16, 2);
lcd.print("It is");
lcd.setCursor(0,1);
lcd.print("decidedly so :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 5:
lcd.begin(16, 2);
lcd.print("Most");
lcd.setCursor(0,1);
lcd.print("likely :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 6:
lcd.begin(16, 2);
lcd.print("Ask again");
lcd.setCursor(0,1);
lcd.print("later :/");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 7:
lcd.begin(16, 2);
lcd.print("My reply is");
lcd.setCursor(0,1);
lcd.print("no :(");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 8:
lcd.begin(16, 2);
lcd.print("Without a");
lcd.setCursor(0,1);
lcd.print("doubt :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 9:
lcd.begin(16, 2);
lcd.print("Outlook good :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 10:
lcd.begin(16, 2);
lcd.print("Better not tell");
lcd.setCursor(0,1);
lcd.print("you now :/");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 11:
lcd.begin(16, 2);
lcd.print("My sources");
lcd.setCursor(0,1);
lcd.print("say no :(");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 12:
lcd.begin(16, 2);
lcd.print("Yes");
lcd.setCursor(0,1);
lcd.print("definitely :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 13:
lcd.begin(16, 2);
lcd.print("Yes :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 14:
lcd.begin(16, 2);
lcd.print("Cannot");
lcd.setCursor(0,1);
lcd.print("predict now :/");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 15:
lcd.begin(16, 2);
lcd.print("Outlook not");
lcd.setCursor(0,1);
lcd.print("so good :(");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 16:
lcd.begin(16, 2);
lcd.print("You may rely");
lcd.setCursor(0,1);
lcd.print("on it :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 17:
lcd.begin(16, 2);
lcd.print("Signs point");
lcd.setCursor(0,1);
lcd.print("to yes :)");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 18:
lcd.begin(16, 2);
lcd.print("Concentrate and");
lcd.setCursor(0,1);
lcd.print("ask again :/");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
case 19:
lcd.begin(16, 2);
lcd.print("Very");
lcd.setCursor(0,1);
lcd.print("doubtful :(");
delay (2500);
lcd.clear();
lcd.print("Ask another");
lcd.setCursor(0,1);
lcd.print("question!");
break;
}
}
}
}
11) Arduino Calculator

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1
RGB LCD Shield Kit, 16x2
Character Display × 1

Jumper wires (generic)

× 1

9V battery (generic)

× 1

Breadboard (generic)

× 1

ABOUT THIS PROJECT

At the end of this project you will know how to use a 16x2 LCD and
Keypad with Arduino and also how easy it is to program for them using
the readily available libraries. You will also understand how to program
your Arduino for accomplishing a particular task.
Materials Required:
Arduino Uno (Any version will work)
16×2 LCD Display
4×4 Keypad
9V Battery
Breadboard and Connecting wires
D0
1st pin of the keyboard
D1
2nd pin of the keyboard
D2
3rd pin of the keyboard
D3
4th pin of the keyboard
D4
5th pin of the keyboard
D5
6th pin of the keyboard
D6
7th pin of the keyboard
D7
8th pin of the keyboard
D8
Register select pin of LCD (pin 4)
D9
Enable pin of LCD (pin 6)
D10
Data pin 4 (pin 11)
D11
Data pin 4 (pin 11)
D12
Data pin 4 (pin 11)
D13
Data pin 4 (pin 11)
+5V
Connected to Vdd pin of LCD (pin 2)
Ground
Connected to Vss, Vee and RW pin of LCD (pin 1, 3 and 5)
Some Arduino boards might show an error while uploading program if
there are anything connected to pin 0 and pin1, so if you experience any
just remove the keypad while uploading the program.
Once your connections are done your hardware will look something like
this below
SCHEMATICS
CODE

*
* Arduino Keypad calculator Program
*/

#include <LiquidCrystal.h> //Header file for LCD from


https://www.arduino.cc/en/Reference/LiquidCrystal
#include <Keypad.h> //Header file for Keypad from https://github.com/Chris--A/Keypad

const byte ROWS = 4; // Four rows


const byte COLS = 4; // Three columns

// Define the Keymap


char keys[ROWS][COLS] = {

{'7','8','9','D'},

{'4','5','6','C'},

{'1','2','3','B'},

{'*','0','#','A'}

};

byte rowPins[ROWS] = { 0, 1, 2, 3 };// Connect keypad ROW0, ROW1, ROW2 and ROW3
to these Arduino pins.
byte colPins[COLS] = { 4, 5, 6, 7 }; // Connect keypad COL0, COL1 and COL2 to these
Arduino pins.

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Create


the Keypad

const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //Pins to which LCD is


connected
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

long Num1,Num2,Number;
char key,action;
boolean result = false;
void setup() {
lcd.begin(16, 2); //We are using a 16*2 LCD display
lcd.print("DIY Calculator"); //Display a intro message
lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print("-CircuitDigest"); //Display a intro message

delay(2000); //Wait for display to show info


lcd.clear(); //Then clean it
}

void loop() {

key = kpd.getKey(); //storing pressed key value in a char

if (key!=NO_KEY)
DetectButtons();

if (result==true)
CalculateResult();

DisplayResult();
}

void DetectButtons()
{
lcd.clear(); //Then clean it
if (key=='*') //If cancel Button is pressed
{Serial.println ("Button Cancel"); Number=Num1=Num2=0; result=false;}

if (key == '1') //If Button 1 is pressed


{Serial.println ("Button 1");
if (Number==0)
Number=1;
else
Number = (Number*10) + 1; //Pressed twice
}

if (key == '4') //If Button 4 is pressed


{Serial.println ("Button 4");
if (Number==0)
Number=4;
else
Number = (Number*10) + 4; //Pressed twice
}

if (key == '7') //If Button 7 is pressed


{Serial.println ("Button 7");
if (Number==0)
Number=7;
else
Number = (Number*10) + 7; //Pressed twice
}

if (key == '0')
{Serial.println ("Button 0"); //Button 0 is Pressed
if (Number==0)
Number=0;
else
Number = (Number*10) + 0; //Pressed twice
}

if (key == '2') //Button 2 is Pressed


{Serial.println ("Button 2");
if (Number==0)
Number=2;
else
Number = (Number*10) + 2; //Pressed twice
}

if (key == '5')
{Serial.println ("Button 5");
if (Number==0)
Number=5;
else
Number = (Number*10) + 5; //Pressed twice
}

if (key == '8')
{Serial.println ("Button 8");
if (Number==0)
Number=8;
else
Number = (Number*10) + 8; //Pressed twice
}

if (key == '#')
{Serial.println ("Button Equal");
Num2=Number;
result = true;
}
if (key == '3')
{Serial.println ("Button 3");
if (Number==0)
Number=3;
else
Number = (Number*10) + 3; //Pressed twice
}

if (key == '6')
{Serial.println ("Button 6");
if (Number==0)
Number=6;
else
Number = (Number*10) + 6; //Pressed twice
}

if (key == '9')
{Serial.println ("Button 9");
if (Number==0)
Number=9;
else
Number = (Number*10) + 9; //Pressed twice
}

if (key == 'A' || key == 'B' || key == 'C' || key == 'D') //Detecting Buttons on Column 4
{
Num1 = Number;
Number =0;
if (key == 'A')
{Serial.println ("Addition"); action = '+';}
if (key == 'B')
{Serial.println ("Subtraction"); action = '-'; }
if (key == 'C')
{Serial.println ("Multiplication"); action = '*';}
if (key == 'D')
{Serial.println ("Devesion"); action = '/';}

delay(100);
}

void CalculateResult()
{
if (action=='+')
Number = Num1+Num2;

if (action=='-')
Number = Num1-Num2;

if (action=='*')
Number = Num1*Num2;

if (action=='/')
Number = Num1/Num2;
}

void DisplayResult()
{
lcd.setCursor(0, 0); // set the cursor to column 0, line 1
lcd.print(Num1); lcd.print(action); lcd.print(Num2);

if (result==true)
{lcd.print(" ="); lcd.print(Number);} //Display the result

lcd.setCursor(0, 1); // set the cursor to column 0, line 1


lcd.print(Number); //Display the result
}
12) Arduino DIY Benchtop Ph Meter

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1
Atlas Scientific Gravity™ Analog
pH Sensor
× 1

Atlas Scientific Consumer Grade


pH Probe
× 1

20x4 LCD Module


× 1

158x90x60mm enclosure
× 1

Mini breadboard
× 1

Resistor 220 ohm

× 1

Resistor 1k ohm

× 1

11mm standoffs and screws


(provided with the pH sensor) × 4
Jumper wires
× 1

Acrylic sheet (plexiglass)


× 1
NECESSARY TOOLS AND MACHINES
Drill, drill bits, drywall cutter bits, files,
screwdrivers, benchtop vise, band saw, glue gun
and glue stick, soldering iron and solder, digital
caliper, ruler
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

In this project, we will be making a benchtop pH meter using the


Gravity analog pH circuit and probe from Atlas Scientific and an
Arduino Uno. Readings will be displayed on a liquid crystal display
(LCD).
Note:
- This meter was developed on a Windows computer. It was not tested
on Mac.
- The enclosure is not waterproof.
Step 1: Prepare Housing
Safety : Remember to take care when handling tools/machinery and to
wear proper safety gear such as goggles, gloves, and respirators.
The housing used is an ABS plastic enclosure. It has to be modified for
the pH meter.
Cut opening for the LCD
a) The LCD is placed in the top portion (cover) of the enclosure. Center
a 98x40mm rectangle on the cover.
b) Put the piece in the vise and drill a 3.2mm (1/8") pilot hole in the
rectangle that was marked off.
c) Use this pilot hole as the start point for the 3.2mm (1/8") drywall
cutting bit. Since this a small job, we will use the bit on the hand drill
rather than a drywall cutting machine. Work on the inside of the
rectangle instead of the lines as it may be a bit difficult to cut in a
straight manner with this bit on the drill.
d) Next, use a hand file to remove the excess material and shape the
rectangle to the required size.

Cut openings for BNC connector and Arduino ports


The openings for the BNC connector and Arduino ports are on the side
of the bottom portion of the enclosure.
a) Using the dimensions provided below, mark the center point for the
circle and outlines for the two rectangles.
b) Put the piece in the vice and cut the openings. The circular opening
is made using drill bits. The rectangular ones are made by following a
similar process used to make the opening for the LCD.
Outfit the base plate to mount components
The base plate is used to mount the Arduino, pH sensor and mini
breadboard. 3.2mm thick acrylic sheet is used.
a) Using a band saw, cut the acrylic sheet to 135x62.5mm.
b) Mark off the positions for the four holes as shown below. Drill
2.38mm (3/32") diameter holes. Countersink the holes on one side of
the plate to a depth of 3mm and diameter of 4.4mm (11/64"). This is
necessary to keep a flat under-surface when the screws are inserted to
hold the standoffs.
c) Attach the 11mm standoffs using the provided screws. The pH sensor
comes with 4 standoffs and screws. Use two of them for the Arduino.
Step 2: Install Electronics in Housing
a) Insert the base plate into the bottom portion of the housing. Keep in
position with screws or hot glue.

b) Mount the pH sensor on the base plate. Secure to standoffs with


screws.
c) Mount the Arduino Uno onto the base plate. Secure to standoffs with
screws.
d) Add the mini breadboard onto the base plate.
e) Solder the header pins to the LCD (pins provided). Insert LCD into
the top portion of the housing and use some hot glue to keep the screen
in place.
Step 3: Wire Electronics Together
Wire the components are shown in the schematic above.
Use the mini breadboard for the 1kΩ and 220Ω and for distributing the
Arduino's 5V and ground pins.
The two resistors are used to set the screen contrast.

Datasheets
Gravity pH sensor, pH probe
Step 4: Finalize Assembly
After the wiring has been completed:
a) Put the top and bottom portions of the housing together using the
provided screws.
b) Connect the probe to the BNC connector.
Step 5: Upload Code Onto Arduino Uno
The code for this project makes use of customized libraries and header
files. You will have to add them to your Arduino IDE to use the code.
The steps below include the process of making this addition to the IDE.
a) Connect the Arduino to your computer and open the IDE. The IDE
can be downloaded from this LINK if you do not have it. Go to Tools -
> Board -> Select Arduino/Genuino Uno. Go to Tools -> Port -> select
the port where the Arduino is connected to.
b) Add Liquid Crystal Display library: In the IDE go to Sketch ->
Include library -> Manage libraries. In the search bar of the Library
Manager enter "liquidcrystal". Look for the package titled
"LiquidCrystal Built-in by Arduino, Adafruit". It may or may not be
installed. If not, select the package and click on install.
c) Add Atlas Gravity sensor library: Download the zip file from the
following LINK. The file will be saved as "Atlas_gravity.zip". In the
IDE go to Sketch -> Include library -> Add.ZIP Library. Locate the
"Atlas_gravity.zip" file and select to add.
d) Next, we have to add the code for the pH meter. Copy the code from
this LINK onto the IDE work panel.
e) Compile and upload the code to the Arduino.
f) The pH readings will then be displayed on the LCD. You can also
view the readings on the serial monitor. To open the serial monitor, go
to Tools -> Serial Monitor or press Ctrl+Shift+M on your keyboard. Set
the baud rate to 9600 and select "Carriage return".
Step 6: Calibrate pH Sensor
Note: If you plan on using an external power supply for the Arduino,
connect it to the Arduino before doing the calibration. This will ensure
that the reference levels are appropriately set, which will aid in the
correct calibration.
This pH meter can be calibrated to one, two or three-points calibration.
Standard buffer solutions (pH 4, 7 and 10) are required
The serial monitor is used for the calibration process. The user will be
able to observe the gradual change in readings as they come to
stabilization and send the appropriate commands.
Calibration data are stored in the EEPROM of the Arduino.
Calibration commands
Low-point: cal, 4
Mid-point: cal, 7
High-point: cal, 10
Clear calibration: cal, clear
Steps
a) Remove the soaker bottle and rinse off the pH probe.
b) Pour some of the pH 4 solution into a cup. Ensure that there is
enough to cover the sensing area of the probe.
c) Place the probe in the cup and stir it around to remove trapped air.
Observe the readings on the serial monitor. Let the probe sit in the
solution until the readings stabilize (small movement from one reading
to the next is normal)
d) After the readings stabilize, enter the command cal, 4 into the serial
monitor. Calibration to pH 4 is now complete.
Repeat steps a-d for pH7 and pH10. Remember to rinse the probe as
you proceed to different buffer solutions.
What about temperature compensation?
The sensor used in this project has an accuracy of +/- 0.2%. The pH
meter will operate within this accuracy in the temperature range of 7 -
46°C. Outside of this range, the meter will have to be modified for
temp compensation. Note: The pH probe can be subjected to a range of
1 − 60 °C.

SCHEMATICS
CODE

/*
Once uploaded, open the serial monitor, set the baud rate to 9600 and append "Carriage
return"
The code allows the user to observe real time pH readings as well as calibrate the sensor.
One, two or three-point calibration can be done.

Calibration commands:
low-point: "cal,4"
mid-point: "cal,7"
high-point: "cal,10"
clear calibration: "cal,clear"
*/

#include "ph_grav.h" //header file for Atlas Scientific gravity pH


sensor
#include "LiquidCrystal.h" //header file for liquid crystal display (lcd)

String inputstring = ""; //a string to hold incoming data from the PC
boolean input_string_complete = false; //a flag to indicate have we received all
the data from the PC
char inputstring_array[10]; //a char array needed for string parsing
Gravity_pH pH = A0; //assign analog pin A0 of Arduino to class
Gravity_pH. connect output of pH sensor to pin A0
LiquidCrystal pH_lcd(2, 3, 4, 5, 6, 7); //make a variable pH_lcd and assign
arduino digital pins to lcd pins (2 -> RS, 3 -> E, 4 to 7 -> D4 to D7)

void setup() {
Serial.begin(9600); //enable serial port
pH_lcd.begin(20, 4); //start lcd interface and define lcd size (20
columns and 4 rows)
pH_lcd.setCursor(0,0); //place cursor on screen at column 1, row 1
pH_lcd.print("--------------------"); //display characters
pH_lcd.setCursor(0,3); //place cursor on screen at column 1, row 4
pH_lcd.print("--------------------"); //display characters
pH_lcd.setCursor(5, 1); //place cursor on screen at column 6, row 2
pH_lcd.print("pH Reading"); //display "pH Reading"
if (pH.begin()) { Serial.println("Loaded EEPROM");}
Serial.println(F("Use commands \"CAL,4\", \"CAL,7\", and \"CAL,10\" to calibrate the
circuit to those respective values"));
Serial.println(F("Use command \"CAL,CLEAR\" to clear the calibration"));
}

void serialEvent() { //if the hardware serial port_0 receives a char


inputstring = Serial.readStringUntil(13); //read the string until we see a <CR>
input_string_complete = true; //set the flag used to tell if we have received a
completed string from the PC
}

void loop() {

if (input_string_complete == true) { //check if data received


inputstring.toCharArray(inputstring_array, 30); //convert the string to a char array
parse_cmd(inputstring_array); //send data to pars_cmd function
input_string_complete = false; //reset the flag used to tell if we have received a
completed string from the PC
inputstring = ""; //clear the string
}
Serial.println(pH.read_ph()); //output pH reading to serial monitor
pH_lcd.setCursor(8, 2); //place cursor on screen at column 9, row 3
pH_lcd.print(pH.read_ph()); //output pH to lcd
delay(1000);
}

void parse_cmd(char* string) { //For calling calibration functions


strupr(string); //convert input string to uppercase

if (strcmp(string, "CAL,4") == 0) { //compare user input string with CAL,4 and if


they match, proceed
pH.cal_low(); //call function for low point calibration
Serial.println("LOW CALIBRATED");
}
else if (strcmp(string, "CAL,7") == 0) { //compare user input string with CAL,7 and if
they match, proceed
pH.cal_mid(); //call function for midpoint calibration
Serial.println("MID CALIBRATED");
}
else if (strcmp(string, "CAL,10") == 0) { //compare user input string with CAL,10 and
if they match, proceed
pH.cal_high(); //call function for highpoint calibration
Serial.println("HIGH CALIBRATED");
}
else if (strcmp(string, "CAL,CLEAR") == 0) { //compare user input string with
CAL,CLEAR and if they match, proceed
pH.cal_clear(); //call function for clearing calibration
Serial.println("CALIBRATION CLEARED");
}
}

13) Arduino Reaction Timer


COMPONENTS AND SUPPLIES
LED (generic)

× 2

SparkFun Pushbutton switch 12mm

× 2

DFRobot I2C 16x2 Arduino LCD


Display Module
× 1
Slide Switch

× 1

Resistor 10k ohm

× 2

Battery Holder, 3 x AAA

× 1

Arduino Micro & Genuino Micro

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

ABOUT THIS PROJECT

I discovered the code somewhere on the Internet and tried it.


All my family loved the game and I decided to assemble it in a funny
case to be able to play.
The work is now finished and it is into the hands of my kids.
It is a very basic project but in a kind of case which hides all elements.
Here are some pictures:

This is how it looks. The BIG button is a hit button and the small red
one on top is "start"
I was able to shrink the system and program only an Atmega328P chip.
Runs on 3 AAA.
Press Start

Round 1 of 5

Round 2 of 5
Average result calculation and showing. The "verdict"
Please do not hesitate to ask me questions if needed.
SCHEMATICS
CODE

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define btnSTART 5
#define btnHIT 7
#define ledTrigger 9
LiquidCrystal_I2C lcd(0x23,20,4);

void setup() {
lcd.init();
lcd.backlight();
pinMode(btnSTART, INPUT_PULLUP);
pinMode(btnHIT, INPUT_PULLUP);
pinMode(ledTrigger, OUTPUT);
digitalWrite(ledTrigger, LOW);
lcd.print("Salut Famille!");
delay(2000);
lcd.clear();
randomSeed(analogRead(0));
}

void loop() {
long timeReaction;
long timeTotal = 0;
lcd.print("Press START!");
while (digitalRead(btnSTART)) {}
delay(10);
while (!digitalRead(btnSTART)) {}
lcd.clear();
lcd.print("Jouez!!!");
delay(1000);
for (int i = 0; i < 5; i++) {
delay(random(500, 5000));
timeReaction = millis();
digitalWrite(ledTrigger, HIGH);
while (digitalRead(btnHIT)) {}
timeReaction = millis() - timeReaction;
timeTotal += timeReaction;
delay(10);
while (!digitalRead(btnHIT)) {}
digitalWrite(ledTrigger, LOW);
lcd.clear();
lcd.print(i + 1);
lcd.print(": ");
lcd.print(timeReaction);
delay(1000);
}
lcd.clear();
lcd.print("Moyenne = ");
lcd.print(timeTotal/5);
delay(10000);
lcd.clear();
}
14) Arduino Quizmo

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1
Adafruit Standard LCD - 16x2
White on Blue
× 1

Adafruit 4x3 Keypad


× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

This project is related to developing a handy gadget to help kids


practice basic arithmetic operations. I decided to make it as my kids
were very lazy to look into the books and come back very soon saying
that they have done it (specially multiplication tables). This gadget
randomly asks different questions and evaluate kids performance.
For this you need a 4x3 keypad to interact with the gadget and an LCD
to show you results.
Once you have setup brightness using the rehestat, you can note down
the values and replace it with fixed resistors or keep it there if you want
the user to adjust brightness as per his/her comfort.
Power up Arduino and it will ask you what kind of quiz you want to
take. Selec appropriate option and it will start. Once you have input
your answer, you need to press * in order to submit and let the gadeget
check your answer. In order to finish the quiz or take next one, press #
and main menu will appear again. You can increase the difficulty level
from the code by changing the maximum range of random number
generator. This gadget currently produces random questions by using
numbers from 1 to 12.
SCHEMATICS
CODE

#include <Keypad.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

long rand1,rand2,ans,ans1,opr,score,total;
char selec,selec1;
boolean quiz=false;
String stringTwo;

const byte ROWS = 4; //four rows


const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[ROWS] = {10, 9, 8, 7}; //connect to the row pinouts of
the keypad
byte colPins[COLS] = {6,1,0}; //connect to the column pinouts of the
keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins,


ROWS, COLS );

void setup(){
lcd.begin(16, 2);
mk_menu();
keypad.addEventListener(keypadEvent);
}

void loop(){
selec = keypad.getKey();
while (selec==NO_KEY){
selec = keypad.getKey();
}
lcd.print(selec);
delay(500);
if (selec!=NO_KEY){
switch(selec){
case '1':
quiz=true;
opr=1;
quiz_sum();
break;
case '2':
quiz=true;
opr=2;
quiz_subt();
break;
case '3':
quiz=true;
opr=3;
quiz_mult();
break;
}
}
}

void mk_menu(){
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("1)+ 2)- 3)x");
lcd.setCursor(0, 1);
lcd.print("Choose: ");
}
void quiz_sum(){
lcd.clear();
lcd.setCursor(0, 0);
rand1=random(1,99);
rand2=random(1,99);
lcd.print("Find ");
lcd.print(rand1);
lcd.print("+");
lcd.print(rand2);
lcd.print("?");
ans1=rand1+rand2;
selec1 = keypad.getKey();
while (selec1==NO_KEY){
selec1 = keypad.getKey();
}
while (quiz){
while (selec1==NO_KEY){
selec1 = keypad.getKey();
}
switch(selec1){
case NO_KEY:
break;
default:
lcd.print(selec1);
stringTwo.concat(selec1);
ans=stringTwo.toInt();
//lcd.print(stringTwo);
selec1=NO_KEY;
break;
}
}
}

void quiz_subt(){
lcd.clear();
lcd.setCursor(0, 0);
rand1=random(1,99);
rand2=random(1,99);
lcd.print("Find ");
if(rand1>=rand2){
lcd.print(rand1);
lcd.print("-");
lcd.print(rand2);
ans1=rand1-rand2;
}
else if(rand1<rand2){
lcd.print(rand2);
lcd.print("-");
lcd.print(rand1);
ans1=rand2-rand1;
}
lcd.print("?");
selec1 = keypad.getKey();
while (selec1==NO_KEY){
selec1 = keypad.getKey();
}
while (quiz){
while (selec1==NO_KEY){
selec1 = keypad.getKey();
}
switch(selec1){
case NO_KEY:
break;
default:
lcd.print(selec1);
stringTwo.concat(selec1);
ans=stringTwo.toInt();
//lcd.print(stringTwo);
selec1=NO_KEY;
break;
}
}
}

void quiz_mult(){
lcd.clear();
lcd.setCursor(0, 0);
rand1=random(1,12);
rand2=random(1,12);
lcd.print("Find ");
lcd.print(rand1);
lcd.print("x");
lcd.print(rand2);
lcd.print("?");
ans1=rand1*rand2;
selec1 = keypad.getKey();
while (selec1==NO_KEY){
selec1 = keypad.getKey();
}
while (quiz){
while (selec1==NO_KEY){
selec1 = keypad.getKey();
}
switch(selec1){
case NO_KEY:
break;
default:
lcd.print(selec1);
stringTwo.concat(selec1);
ans=stringTwo.toInt();
//lcd.print(stringTwo);
selec1=NO_KEY;
break;
}
}
}

void chk_ans(){
lcd.clear();
if (ans1==ans){
lcd.clear();
lcd.print("Correct");
score=score+1;
}
else {
lcd.clear();
lcd.print("Incorrect");
}
}
void keypadEvent(KeypadEvent key){
switch (keypad.getState()){
case PRESSED:
if (key == '*') {
chk_ans();
total=total+1;
stringTwo="";
delay(400);
if(opr==1){
quiz_sum();
}
else if(opr==2){
quiz_subt();
}
else if(opr==3){
quiz_mult();
}
}
else if (key == '#') {
quiz=false;
stringTwo="";
lcd.clear();
lcd.print("Your Score: ");
lcd.print(score);
lcd.print("/");
lcd.print(total);
delay(1500);
score=0;
total=0;
mk_menu();
loop();
}
break;
}
}
15) Arduino Model Train Control

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO
Or any compatible (i used
× 1
sainsmart mega 2560)

Arduino Motor Shield R3


× 1

LED white
× 2

Photo resistor

× 2

Resistor 10k ohm

× 2

Resistor 330 ohm

× 2

ABOUT THIS PROJECT

Like many people, my wish is a nice model train, therefore I made a nice
layout plan, bought a starter set, made a table etc. It takes a long time, of
course, to build a complicated layout and in the meantime you want to
(test)ride on the track you have so far.
You can of course do so just with your transformer, but if you do not pay
attention you drive off the track. And model trains are fragile, a drop on
the floor will do damage. So the plan is a back and forth automation.
Something like this: Arduino-railroad.
All due respect to the maker but if you pop each time against a fence and
reverse the motor directly, it will damage the train or the gear at some
time.
I figured two gates with an LED and an LDR will sense the train.

Gate of LED and LDR


And let the Arduino decelerate, reverse and accelerate the train.
The train blocks the light

SCHEMATICS
CODE

/*
Train control
This code is developed to "test" drive
a model train between two gates made of a LED and LDR.

Parts required:
1 - arduino uno/mega or compatible
1 - arduino motor shield R3
2 - Led brite white (5mm)
2 - Ldr (A 9013 photo resistor 5mm)
2 - 10K resistor
2 - 220 Ohm resistor
1 - model train

Created 4 October 2016


by Kitemasters

This code is part of the public domain


*/
// --------CONSTANTS (won't change)---------------

int sens_L_Pin = A4; // the pin number for ldr L


int sens_R_Pin = A5; // the pin number for ldr R
int led_L_Pin = 4; // the pin number for the L LED
int led_R_Pin = 5; // the pin number for the R LED
int motor_Pin = 3; // the pin number for the motor speed
int brake_Pin = 9; // the pin number for the motor brake
int direction_Pin = 12; // the pin number for the motor direction
int current_sens_Pin = A0; // the pin number for the current sensor

int read_sens_Interval = 200; // millisecs between reading sensors


int motor_Acc_Interval = 100; // millisecs between acceleration steps
int motor_Dec_Interval = 10; // millisecs between deceleration steps

//------------ VARIABLES (will change)---------------------

unsigned long currentMillis = 0; // stores the value of millis() in each iteration of


loop()
unsigned long previous_sens_Millis = 0; // will store the last time sensors are read
unsigned long previous_Acc_Millis = 0; // will store time of last acceleration step
unsigned long previous_Dec_Millis = 0; // will store time of last deceleration step

int sensLreading = 0; // declare variable and set value for left sensor
reading
int sensRreading = 0; // declare variable and set value for right sensor
reading
int max_Speed = 200; // declare variable and set value for maximum Speed
(0 to 255)
int Speed = 0; // declare variable and set value for current Speed (0 to
255)
boolean direct = HIGH; // declare variable and set value for direction to
HIGH (HIGH = left)

#define STATE_START 1 // declare value 0 to be STATE_START


#define STATE_RUN 2 // declare value 1 to be STATE_RUN
#define STATE_DECELERATE 3 // declare value 2 to be
STATE_DECELERATE
#define STATE_TURN 4 // declare value 3 to be STATE_TURN
#define STATE_ACCELERATE 5 // declare value 4 to be
STATE_ACCELERATE

int state = STATE_START; // declare variable "state" and set value to


STATE_START

//========================================

void setup() {

Serial.begin(9600);

pinMode(led_L_Pin, OUTPUT); // set led_L_Pin as output


pinMode(led_R_Pin, OUTPUT); // set led_R_Pin as output
pinMode(motor_Pin, OUTPUT); // set motor_Pin as output
pinMode(brake_Pin, OUTPUT); // set brake_Pin as output
pinMode(direction_Pin, OUTPUT); // set direction_Pin as output
pinMode(sens_L_Pin, INPUT); // set sens_L_Pin as input
pinMode(sens_R_Pin, INPUT); // set sens_R_Pin as input
pinMode(current_sens_Pin, INPUT); // set current_sens_Pin as input

}
//========================================

void loop() {

currentMillis = millis(); // store the latest value of millis()


read_sens(); // read the sensors
switch (state) // state switch
{
case STATE_START:
Start();
break;

case STATE_ACCELERATE:
Accelerate();
break;

case STATE_DECELERATE:
Decelerate();
break;

case STATE_TURN:
Turn();
break;

case STATE_RUN:
break;
}
}
//========================================

void read_sens() {

if (currentMillis - previous_sens_Millis >= 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) { // if conditions are throu, the
train reached left gate***
digitalWrite(led_L_Pin, LOW); // turn left LED off
digitalWrite(led_R_Pin, HIGH); // turn right LED on
state = STATE_DECELERATE; // set state to "decelerate"
previous_Dec_Millis = currentMillis; // set previous_Dec_Millis to
current time
}

if (sensRreading > 200 && direct == LOW) { // 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
× 1
sainsmart mega 2560)
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
× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1
with I2C connection

IR receiver (generic)
× 1

Jumper wires (generic)

× 11

Any Remote Control


× 1
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 <IRremote.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
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 <",
" Press key ",
"You have to", // if you don't want this howToPlay you can delete from here ...
"press the key,",
"that you see on",
"the screen, when",
"it is beetween",
"the fences (#).",
"It ist getting",
"faster and there",
"will be symbols",
"that you do not",
"have to hit!",
"Try to get to",
"Level 10 and win",
"the game. Before",
"you start, you",
"have to define",
"the keys on your",
"remote control",
"to play the game", // ... until here. Leave the last lines for propper work!
" Have fun !!",
""
};

String keyNames[] = {"up", "down", "right", "left", "ok", "+", "-", "#", "*"};
String keySymb[] = {"", "", "", "", "", "", "", "", ""};
long keys[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int keycount = 7;

int lev;
int xpos = 1;
int xadd = 1;
int xleft;
int xright;
int xstart = 0;
int xend = 15;

int actSym = 0;
int score; // All together score
int scorePerLev; // Symbols in actual level
int scoreNextLev = 50; // Symbols until next level

int gameState = -1;

bool pressed = false;

IRrecv irrecv(RECV_PIN);
decode_results results;

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line
display

void setup()
{
Serial.begin(9600);
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.createChar(up, up1);
lcd.createChar(down, down1);
lcd.createChar(ok, ok1);
keySymb[0] = "\3";
keySymb[1] = "\1";
keySymb[2] = "\176";
keySymb[3] = "\177";
keySymb[4] = "\2";
keySymb[5] = "+";
keySymb[6] = "-";
keySymb[7] = "#";
keySymb[8] = "*";

irrecv.enableIRIn(); // Start the receiver

info(); //howtoplay show once at the start, can be removed when you know how to play
randomSeed(analogRead(1));
}

void loop()
{

// define keys only once


// gameState= -1
// ################################
if (gameState == -1) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Define Keys to");
lcd.setCursor(0, 1);
lcd.print("play the game...");
delay(3000);
pressed = false;
for (int i = 0; i < keycount; i++) { // 0 und 5
pressed = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Key for:");
lcd.print(keyNames[i]);
while (pressed != true) {
if (irrecv.decode(&results)) {
keys[i] = results.value;
lcd.setCursor(0, 1);
lcd.print(" ok!");
Serial.println(keys[i]);
delay(500);
irrecv.resume(); // Receive the next value
pressed = true;
}
}
pressed = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Repaet key!");
lcd.print(keyNames[i]);
irrecv.resume();
while (pressed != true) {
if (irrecv.decode(&results)) {
if (keys[i] == results.value) {
lcd.setCursor(0, 1);
lcd.print("is the same!");
delay(500);
pressed = true;
} else {
lcd.setCursor(0, 1);
lcd.print("wrong!");
delay(500);
lcd.setCursor(0, 1);
lcd.print(" ");
}
irrecv.resume();
}
}
}
gameState = 0; // ok to select level
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Keys done!");
delay(2000);
}

// Select Level
// gameState=0
//###########################
if (gameState == 0) {
lev = 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Level+ok");
lcd.setCursor(0, 1);
lcd.print("Level: ");
lcd.print(lev);
irrecv.resume();
pressed = false;
Serial.println("Level");
Serial.println(pressed);
while (pressed != true) {
if (irrecv.decode(&results)) {
Serial.println(results.value);
if (results.value == keys[0]) lev++;
if (results.value == keys[1]) lev--;
if (results.value == keys[4]) pressed = true;
if (lev < 1) lev = 1;
if (lev > 10) lev = 10;
lcd.setCursor(7, 1);
lcd.print(lev);
lcd.print(" ");
irrecv.resume();
}
delay(250);
}
lcd.setCursor(0, 0);
lcd.print("Ok! Play in ");
delay(2000);
lcd.clear();
gameState = 1; // Main gameplay
score = 0;
scorePerLev = 0;
keycount = 7;
xleft = 4;
xright = 11;
drawField("");
irrecv.resume();
Serial.println("Level Set");
}

// Main Game
// gameState=1
//###############################
if (gameState == 1) {
xpos = 0;
xadd = 1;
int k = 0;
bool rightkey = false;
pressed = false;
actSym = floor(random(0, keycount));
while (pressed != true) {
Serial.println(xpos);
if (irrecv.decode(&results)) {
for (int i = 0; i < keycount; i++) {
if (results.value == keys[i]) {
rightkey = true;
k = i;
}
}
if (rightkey == true) {
scorePerLev++;
if (xpos <= xleft || xpos >= xright) {
score = score - (4 + lev);
// negativ sound
}
if (actSym == k) {
lcd.setCursor(xpos, 1);
lcd.print(" ");
score++;
drawField("");
changeDirection();
} else {
score = score - (2 + lev);
drawField(" :( ");
// negativ sound
}
actSym = floor(random(0, keycount));
rightkey = false;
}
delay(10);
irrecv.resume();
if (scorePerLev == scoreNextLev) {
scorePerLev = 0;
lev++;
drawField("");
if (lev < 11) {
lcd.setCursor(0, 1);
lcd.print("Next level!");
waitForOK();
// Check for score and display message here later
lcd.setCursor(0, 1);
lcd.print(" ");
} else {
gameState = 5;
pressed = true;
}
}
}
lcd.setCursor(xpos, 1);
lcd.print(" ");
xpos = xpos + xadd;
if (xpos == xend + 1 || xpos == xstart - 1) {
if (actSym < 7) {
score = score - (2 * (lev + 5));
drawField(" :( ");
} else {
drawField("");
}
changeDirection();
actSym = floor(random(0, keycount));
// negativ sound
}
lcd.setCursor(xpos, 1);
lcd.print(keySymb[actSym]);
delay(200 - (lev * 10));
if (score < 0) {
gameState = 9;
pressed = true;
}
} // Main Game loop End

// Win
// ##################
if (gameState == 5) {
// positiv sound
lcd.setCursor(0, 1);
lcd.print("You win the Game");
lcd.setCursor(0, 0);
lcd.print("Bravo! ");
waitForOK();
gameState = 0;
}

// Game Over
// ##################
if (gameState == 9) {
// negativ sound
for (int i = 0; i < 5; i++) {
lcd.setCursor(0, 1);
lcd.print(" ");
delay(200);
lcd.setCursor(0, 1);
lcd.print(" Game over! ");
delay(300);
}
waitForOK();
gameState = 0;
}

void info () {
int i = 0;
while (howtoplay[i] != "") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(howtoplay[i]);
lcd.setCursor(0, 1);
lcd.print(howtoplay[i + 1]);
delay(300);
waitForKey();
i++;
}
irrecv.resume();
}

void drawField(String empty) {


Serial.println("drawField");
int SCur;
if (empty == "") empty = " ";
lcd.setCursor(0, 0);
lcd.print("################");
if (lev > 3) {
xleft = floor(random(4, 7));
xright = xleft + 7;
if (lev > 6) xright = xleft + 6;
if (lev > 9) xright = xleft + 5;
}
if (lev > 4) keycount = 8;
if (lev > 6) keycount = 9;
lcd.setCursor(xleft + 1, 0);
lcd.print(empty.substring(0, xright - xleft - 1));
lcd.setCursor(0, 0);
lcd.print("L");
lcd.print(lev);
if (score < 1000) SCur = 13;
if (score < 100) SCur = 14;
if (score < 10) SCur = 15;
if (score < 0) SCur = 14;
lcd.setCursor(SCur, 0);
lcd.print(score);
}

void changeDirection() {
xpos = xstart;
xadd = 1;
if (lev > 3) {
int dir = floor(random(0, 2));
if (dir == 1) {
xpos = xend;
xadd = -1;
}
}
}

void waitForKey () {
bool press = false;
irrecv.resume();
while (press == false) {
if (irrecv.decode(&results)) {
if (results.value != 0) press = true;
irrecv.resume();
delay(200);
}
}
}

void waitForOK() {
delay(1000);
bool press = false;
irrecv.resume();
while (press == false) {
if (irrecv.decode(&results)) {
if (results.value == keys[4]) press = true;
irrecv.resume();
delay(200);
}
}
}
18) Arduino DIY PH Dosing Pump

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

pH UP/pH DOWN Solution


× 1
Resistor 4.75k ohm
× 2

5 pin header
× 2

Atlas Scientific Peristaltic Pump


Kit
× 2

Atlas Scientific pH Sensor Kit

× 1

Breadboard (generic)

× 1

Male/Male Jumper Wires


× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

We will be making a pH dosing system. It has the capability of


maintaining the sample within a defined pH range, in this case, 8-8.5.
If the readings go out of range, small amounts of either pH UP or pH
DOWN solution is automatically added to the sample until the readings
return within the limits. The pH level will be monitored by the EZO pH
sensor while the UP/DOWN solutions will be dispensed
using peristaltic pumps. Operation is via I2C protocol and readings are
displayed on the Arduino serial monitor
Step 1: Pre-assembly Requirements
a) Calibrate pH sensor and pumps.
b) Set the pH sensor and pumps protocol to I2C and each device needs
a unique I2C address. In accordance with the sample code for this
project, the following addresses are used: pH sensor address is 99,
pump for pH UP solution is 103 and pump for pH DOWN solution is
104. For information on how to change between modes and set
addresses, refer to this LINK.
The calibration and the switch to I2C MUST be done before
implementing the sensors into this project.
Step 2: Assemble Hardware
Connect the hardware as shown in the schematic.
The peristaltic pump has two power lines. The line that goes to the
Arduino's 5V pin is for the circuitry attached to the pump while the
external 12V supply is for the pump itself. The five pin headers are
used to mount the data cables of the pumps to the breadboard after
which jumper wires make the appropriate connections to the Arduino.
The two 4.7kΩ resistors serve as pull up resistors for the SDA (Serial
Data) and SCL (Serial Clock) lines.
Step 3: Load Program onto Arduino
The code for this project makes use of a customized library and header
file for the EZO circuits in I2C mode. You will have to add them to
your Arduino IDE in order to use the code. The steps below include the
process of making this addition to the IDE.
a) Download Ezo_I2c_lib, a zip folder from GitHub onto your
computer.
b) On your computer, open the Arduino IDE (You can download the
IDE from HERE if you do not have it).
c) In the IDE, go to Sketch -> Include Library -> Add.ZIP Library ->
Select the Ezo_I2c_lib folder you just downloaded. The appropriate
files are now included.
d) Copy the code from pH_dosing_pump onto your Arduino work
panel. You can also access this code from the Ezo_I2c_lib folder
downloaded above.
e) Compile and upload the pH_dosing_pump code to your Arduino
UNO.
f) Readings are displayed on the serial monitor. To open the serial
monitor, go to Tools -> Serial Monitor or press Ctrl+Shift+M on your
keyboard. Set the baud rate to 9600 and select "Carriage return". The
pH readings should display and the pumps will be triggered
accordingly to dispense pH UP and pH DOWN solution. Remember
this sample code takes into consideration the pH between 8-8.5, so the
pumps will only turn on when out of this range.

SCHEMATICS
CODE

/*

It was tested on an Arduino UNO.


Real time pH monitoring is done using the EZO pH sensor and two EZO
PMP. The pumps dispense pH UP and pH DOWN solutions into the
sample and they are triggered in accordance with the current pH reading.
The goal is to maintain the pH level of the sample between 8 and 8.5
The sensors must be calibrated and switched to I2C mode before using this
code. The ability to send commands to the sensors is not incorporated
here.
After uploading the code to your arduino, open the serial monitor, set the
baud rate to 9600 and select "Carriage return". The pH dosing system is
now active.*/

#include <Ezo_i2c.h> //include the EZO I2C library from


https://github.com/Atlas-Scientific/Ezo_I2c_lib
#include <Wire.h> //include arduinos i2c library

Ezo_board PH = Ezo_board(99, "PH"); //creat a PH


circuit object, whose address is 99 and name is "PH"
Ezo_board PMP_UP = Ezo_board(103, "PMP_UP"); //create a
pump circuit object, whose address is 103 and name is "PMP_UP". This
pump dispenses pH up solution.
Ezo_board PMP_DOWN = Ezo_board(104, "PMP_DOWN");
//create a pump circuit object, whose address is 104 and name is
"PMP_DOWN". This pump dispenses pH down solution.

bool reading_request_phase = true; //selects our phase


uint32_t next_poll_time = 0; //holds the next time we
receive a response, in milliseconds
const unsigned int response_delay = 1000; //how long we
wait to receive a response, in milliseconds

void setup() {
Wire.begin(); //start the I2C
Serial.begin(9600); //start the serial
communication to the computer
}

void loop() {
if (reading_request_phase) { //if were in the phase
where we ask for a reading

//send a read command. we use this command instead of


PH.send_cmd("R");
//to let the library know to parse the reading
PH.send_read_cmd();

next_poll_time = millis() + response_delay; //set when the


response will arrive
reading_request_phase = false; //switch to the receiving
phase
}
else { //if were in the receiving phase
if (millis() >= next_poll_time) { //and its time to get the
response

receive_reading(PH); //get the reading from the PH


circuit
Serial.print(" ");
if (PH.get_last_received_reading() <= 8) { //test
condition against pH reading
Serial.println("PH LEVEL LOW,PMP_UP = ON");
PMP_UP.send_cmd_with_num("d,", 0.5); //if condition is true,
send command to turn on pump (called PMP_UP) and dispense pH up
solution, in amounts of 0.5ml. Pump turns clockwise.
}
else {
PMP_UP.send_cmd("x"); //if condition is false, send
command to turn off pump (called PMP_UP)
}

if (PH.get_last_received_reading() >= 8.5) { //test


condition against pH reading
Serial.println("PH LEVEL HIGH,PMP_DOWN = ON");
PMP_DOWN.send_cmd_with_num("d,", -0.5); //if condition is
true, send command to turn on pump (called PMP_DOWN) and dispense
pH down solution, in amounts of 0.5ml. Pump turns counter-clockwise.
}
else {
PMP_DOWN.send_cmd("x"); //if condition is false,
send command to turn off pump (called PMP_DOWN)
}

Serial.println();
reading_request_phase = true; //switch back to asking for
readings
}
}
}

void receive_reading(Ezo_board &Sensor) { // function to


decode the reading after the read command was issued
Serial.print(Sensor.get_name()); Serial.print(": "); // print the name of
the circuit getting the reading

Sensor.receive_read_cmd(); //get the response data


and put it into the [Sensor].reading variable if successful

switch (Sensor.get_error()) { //switch case based on


what the response code is.
case Ezo_board::SUCCESS:
Serial.print(Sensor.get_last_received_reading()); //the
command was successful, print the reading
break;

case Ezo_board::FAIL:
Serial.print("Failed "); //means the command has
failed.
break;

case Ezo_board::NOT_READY:
Serial.print("Pending "); //the command has not yet
been finished calculating.
break;

case Ezo_board::NO_DATA:
Serial.print("No Data "); //the sensor has no data to
send.
break;
}
}
19) Arduino Simple Lap Counter for Swimming
COMPONENTS AND SUPPLIES
Magconn Developer Kit
× 1

Arduino Nano R3

× 1

USB Li-Po Battery Charger PCBA


× 1

Li-Po Battery 900mAh


× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Now the weather here is very hot because it is summer. I went to the
pool with my primary school son to avoid the heat, and I saw people
swimming several times on the swimming track. How many laps did
they turn? When you learn to swim, count how many turns you have
made to measure your momentum. But most people forget the count.
There is a wrist watch or a finger counter, but it is a little
uncomfortable when swimming. When swimming, it is better not to do
anything. I made an intuitively waterproof lap-counter. Simply press it
to go up once. I would like to implement many functions, but step by
step.
Materials
There are some great conditions. The first is battery use, the second is
waterproof, and the third is convenience. The battery should be
rechargeable. Because you do not have to open the case when it's
completely discharged. So I found connectors and switches that are
waterproof. The case recycled the phone accessary case. I think that it
was good to recycle when I finished.
Assembling the Case
The lap-counter has a waterproof toggle switch and a waterproof
Magconn connector. I bought the Lithium-Polymer battery and
Lithium-rechargeable PCBA that I had inexpensively. The back side of
the Samsung mobile phone case was machined to match the Magconn
connector, and the magnet was attached and closed with epoxy. I added
four more because I think one magnet is not enough. The connector is
closed with epoxy and glue.
Build Circuit
I built a circuit on the breadboard and implemented the behavior. The
counter is fine. The four corners of the switch are for height
adjustment. After confirming that it works well, I put it in the case and
finished it with silicon. When using glue gun, be careful because case
may melt at high temperature.
Waterproofing should be good. It was made better than I thought. I was
worried about the phone case, but the recycle case became the key
point.
Waterproof Test
I tried the waterproof test in the water of the pool. There is a magnet on
the back of the case, and if there is an iron plate on the outside, it
attaches unconditionally. When there is no iron plate, a sucker plate can
be used.

SCHEMATICS
CODE

const byte numeral[10] = {


//ABCDEFG dp//
B11111100, //0
B01100000, //1
B11011010, //2
B11110010, //3
B01100110, //4
B10110110, //5
B00111110, //6
B11100000, //7
B11111110, //8
B11100110, //9
};

// dp, G, F, E, D, C, B, A
const int segmentPins[8] = { 9,8,7,6,5,4,3,2 };
const int nbrDigits = 2;
const int digitPins[nbrDigits] = { 12,13 };
const int buttonPin = 11;
int buttonState; // the current reading from the input pin
int lastButtonState = HIGH; // the previous reading from the input pin
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
int value = -1;

void setup()
{
for(int i=0; i<8; i++)
{
pinMode(segmentPins[i], OUTPUT);
}
for(int i=0; i<nbrDigits; i++)
{
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], 1);
}
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH); //
}

void loop()
{
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) { // reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
value = value + 1;
}
}
}
lastButtonState = reading;
showNumber(value);
}

void showNumber(int number)


{
if(number == 0)
showDigit(0, nbrDigits-1);
else
{
for(int digit = nbrDigits-1; digit>=0; digit--)
{
if (number>0)
{
showDigit(number%10, digit);
number = number/10;
}
}
}
}

void showDigit(int number, int digit)


{
//boolean isBitSet;
digitalWrite(digitPins[digit],0); //1
for (int segment = 1; segment <8 ; segment++) //segment A ~ dp
{
boolean isBitSet = bitRead(numeral[number], segment); //byte numeral[number] segment
digitalWrite(segmentPins[segment], isBitSet);
}
//isBitSet = !isBitSet
delay(5);
digitalWrite(digitPins[digit], 1);
}
20) Arduino Add Animated Lighting to Your Projects
COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

NeoPixel strip

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Simple DIY Animated Marquee Lighting


This a simple tutorial to add animated lighting to your arcade cabinet
or other projects. It can be used for (back-)lighting marquees and many
other purposes.
You will need an Arduino Nano (or compatible board), a strip of
NeoPixels, and 3 wires.

Short Setup
Hardware: Solder three wires from the Arduino Nano to the NeoPixel
strip: 5V, digital signal (I chose pin 2 on the Arduino) and ground.
Tip: Use a piece of heat shrink to tie the cables together, especially the
led strip (make sure the solder connections are covered). This will
prevent the solder connections from coming loose.
Code: Set the number of LEDs of the connected strip in the sketch
code, upload it to the Arduino and test it. I used a 'walking', flashing
and pulsing animation in the sketch, only using the color white. You
can adjust the code to do all sorts of animations and use many colors.
Or just use simple a backlight, whatever you prefer.
The build: I cut 2 pieces of cardboard which fit snugly in my cabinet.
One piece is used as the background to glue the neopixel strip on. The
other strip is placed flat behind the bottom of the marquee to prevent
light from the neopixels shining down directly. Afterward I had to cut
off some small edges to make it fit my cabinet.
I put a few pieces of gaffa tape on the cardboard to make them black. I
glued the neopixel strip on the cardboard and taped the wires and nano
to the back of the cardboard.
Put the 2 parts in the cabinet and attach a USB cable from the nano to a
5V power source. In my cabinet it is connected to a USB port of a
Raspberry Pi.
Then place the stock marquee back or create your own to customize
your build. I created a simple one, printed it on photo paper and cut it
to fit the marquee.
Tip: The end result will be even better if you have your design printed
on film by a professional printing company.
Libraries
The sketch needs one library:
Adafruit NeoPixel library
SCHEMATICS
CODE

/*
**********************************************************************
* Marquee lighting with Neopixels by ericBcreator
* simple script for lighting an (arcade) marquee
**********************************************************************
*
* components:
* - Neopixel strip
* - Arduino Nano
*
* This code is free for personal use, not for commercial purposes.
* Please leave this header intact.
*/

//
// include the libraries
//

#include <Adafruit_NeoPixel.h>

#define PIN
2
// define the pin the strip is connected to

//
// setup variables and initialize the neopixel strip
//

int numOfLeds =
11;
the numbers of leds on the strip
int minBrightness =
80; // the
minimum brightness of the pulsing and flashing (0-255)
int maxBrightness =
255; // the
maximum brightness of the pulsing and flashing (0-255)
int walkingLedsDelay =
250; // the delay in ms
for the walking leds
int flashDelay =
250;
the delay in ms for the flashing leds
int numOfFlashLoops =
3; // the
number of times the leds flash
int numOfPulseLoops =
10; // the
number of times the leds puls from min to max
int pulseDelay =
20;
the delay in ms when pulsing from min to max and vice verse

Adafruit_NeoPixel strip = Adafruit_NeoPixel(numOfLeds, PIN);

//
// setup
//

void setup() {
strip.begin();
}

//
// main loop
//

void loop() {
walkingLeds();
show the walking leds
flashLeds();
// flash the leds

for (int i = 0; i < numOfPulseLoops; i++) // puls the leds


pulseBrightness();
}

//
// functions
//

void walkingLeds() {
setLedColorsToZero();
strip.setBrightness(maxBrightness);
strip.show();

for (int x = numOfLeds; x > 0; x--) {


strip.setPixelColor(x, strip.Color(255, 255, 255));
strip.show();
delay(walkingLedsDelay );
strip.setPixelColor(x, 0);
strip.show();
}
}
void flashLeds() {
setLedColors();

for (int i = 0; i < numOfFlashLoops; i++) {


strip.setBrightness(maxBrightness);
strip.show();
delay(flashDelay );

strip.setBrightness(minBrightness);
strip.show();
delay(flashDelay );
}
}
void pulseBrightness() {
setLedColors();

for (int i = minBrightness; i < maxBrightness; i++) {


strip.setBrightness(i);
strip.show();
delay(pulseDelay);
}

for (int i = maxBrightness; i > minBrightness; i--) {


strip.setBrightness(i);
strip.show();
delay(pulseDelay);
}
}

void setLedColors() {
for (int x = 0; x < numOfLeds; x++)
strip.setPixelColor(x, strip.Color(255, 255, 255));
}

void setLedColorsToZero() {
for (int x = 0; x < numOfLeds; x++)
strip.setPixelColor(x, strip.Color(0, 0, 0));
}

21) Arduino 8X8 Matrix LED Snake Game


COMPONENTS AND SUPPLIES
PHPoC Shield for Arduino

× 1

Arduino UNO & Genuino UNO

× 1

Adafruit 8x8 Bi-color LED


Matrix × 1
Jumper wires (generic)

× 1

ABOUT THIS PROJECT


It is the snake game on the 8x8 matrix LED by smartphone motion.
When user tilts the smartphone to one of 4 directions, the direction
value is sent to Arduino through HTML5 WebSocket. Then the snake
changes its direction.
SCHEMATICS

LED ----- PHPoC Shield


VCC ----- 5V
GND ----- GND
SDA ----- A4(SDA)
SCL ----- A5(SCL)
CODE

Arduino Source code

/***************************************************
This is a library for our I2C LED Backpacks

Designed specifically to work with the Adafruit LED Matrix backpacks


----> http://www.adafruit.com/products/872
----> http://www.adafruit.com/products/871
----> http://www.adafruit.com/products/870

These displays use I2C to communicate, 2 pins are required to


interface. There are multiple selectable I2C addresses. For backpacks
with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
with 3 Address Select pins: 0x70 thru 0x77

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h>
#include "SPI.h"
#include "Phpoc.h"

PhpocServer server(80);

// LED face
static const uint8_t PROGMEM
smile_bmp[] =
{ B00111100,
B01000010,
B10100101,
B10000001,
B10100101,
B10011001,
B01000010,
B00111100 },
frown_bmp[] =
{ B00111100,
B01000010,
B10100101,
B10000001,
B10011001,
B10100101,
B01000010,
B00111100 };

// direction
const int TOP = 0;
const int RIGHT = 1;
const int BOTTOM = 2;
const int LEFT = 3;

// Snake
const int MAX_SNAKE_LENGTH = 15;

// Variables
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix(); // Display
int direction = TOP; // direction of movement
int snakeX[MAX_SNAKE_LENGTH]; // X-coordinates of snake
int snakeY[MAX_SNAKE_LENGTH]; // Y-coordinates of snake
int snakeLength = 1; // nr of parts of snake
unsigned long prevTime = 0; // for gamedelay (ms)
unsigned long delayTime = 500; // Game step in ms

int fruitX, fruitY;


unsigned long fruitPrevTime = 0;
unsigned long fruitBlinkTime = 1000/250;
int fruitLed = LED_RED;
int matrixColor;

void setup(){
Serial.begin(9600);
while(!Serial)
;

Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
server.beginWebSocket("snake");

Serial.print("WebSocket server address : ");


Serial.println(Phpoc.localIP());

Serial.println("Game is started.");
randomSeed(analogRead(0));

// Init led matrix


matrix.begin(0x70);
matrix.setRotation(3);

// init snake
snakeX[0] = 4;
snakeY[0] = 7;
for(int i=1; i<MAX_SNAKE_LENGTH; i++)
snakeX[i] = snakeY[i] = -1;

makeFruit();

printString("S");
}

void loop(){
checkButtons();

unsigned long currentTime = millis();


if(currentTime - prevTime >= delayTime)
{
nextstep();
prevTime = currentTime;
}

draw();
}

void checkButtons(){

// wait for a new client:


PhpocClient client = server.available();

if (client)
{
if (client.available() > 0)
{
// read the bytes incoming from the client:
char thisChar = client.read();

if(thisChar == '0')
direction = TOP;
if(thisChar == '1')
direction = LEFT;
if(thisChar == '2')
direction = RIGHT;
if(thisChar == '3')
direction = BOTTOM;
}
}
}

void draw(){
matrix.clear();
drawSnake();
drawFruit();
matrix.writeDisplay();
}

void drawSnake(){
for(int i=0; i<snakeLength; i++)
matrix.drawPixel(snakeX[i], snakeY[i], LED_GREEN);
}

void drawFruit(){
if(inPlayField(fruitX, fruitY)){
unsigned long currenttime = millis();
if(currenttime - fruitPrevTime >= fruitBlinkTime)
{
fruitLed = (fruitLed == LED_RED) ? LED_OFF : LED_RED;
fruitPrevTime = currenttime;
}
matrix.drawPixel(fruitX, fruitY, fruitLed);
}
}

boolean inPlayField(int x, int y){


return (x>=0) && (x<8) && (y>=0) && (y<8);
}

void nextstep(){
for(int i = snakeLength; i > 0; i--)
{
if((direction == RIGHT) && (snakeX[0]-snakeLength == 7))
snakeX[0] = -1;
else if((direction == LEFT) && (snakeX[0]+ snakeLength == 0))
snakeX[0] = 8;
else
snakeX[i] = snakeX[i-1];

if((direction == TOP) && (snakeY[0]+snakeLength == 0))


snakeY[0] = 8;
else if((direction == BOTTOM) && (snakeY[0]-snakeLength == 7))
snakeY[0] = -1;
else
snakeY[i] = snakeY[i-1];
}

switch(direction)
{
case TOP:
snakeY[0] = snakeY[0]-1;
break;
case RIGHT:
snakeX[0] = snakeX[0]+1;
break;
case BOTTOM:
snakeY[0] = snakeY[0]+1;
break;
case LEFT:
snakeX[0]=snakeX[0]-1;
break;
}

if((snakeX[0] == fruitX) && (snakeY[0] == fruitY))


{
snakeLength++;
if(snakeLength < MAX_SNAKE_LENGTH)
makeFruit();
else
fruitX = fruitY = -1;

}
snakeCheck();
}

void makeFruit(){
int x, y;
x = random(0, 8);
y = random(0, 8);
while(isPartOfSnake(x, y)){
x = random(0, 8);
y = random(0, 8);
}
fruitX = x;
fruitY = y;
}

boolean isPartOfSnake(int x, int y){


for(int i=0; i<snakeLength-1; i++)
{
if((x == snakeX[i]) && (y == snakeY[i]))
return true;
}
return false;
}

void snakeCheck(){
for(int i=1; i<snakeLength; i++)
{
// snake touches itself
if((snakeX[0] == snakeX[i]) && (snakeY[0] == snakeY[i]))
userLose();
}
if (snakeLength == MAX_SNAKE_LENGTH)
userWin();
}
void userLose(){
Serial.println("Game Over");
printString("O");

matrix.clear();
matrix.drawBitmap(0, 0, frown_bmp, 8, 8, LED_RED);
matrix.writeDisplay();
delay(1000);

snakeLength = 1;
setup();
loop();
}

void userWin(){
Serial.println("You Win");
printString("W");

matrix.clear();
matrix.drawBitmap(0, 0, smile_bmp, 8, 8, LED_GREEN);
matrix.writeDisplay();
delay(1000);

snakeLength = 1;
setup();
loop();
}

void printString(String str){


String matrixComment;

matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely


matrix.setTextSize(1);

if (str == "O")
{
matrixComment = "Game Over!";
matrixColor = LED_RED;
}
else if (str == "W")
{
matrixComment = "You Win!";
matrixColor = LED_GREEN;
}
else if (str == "S")
{
matrixComment = "Go!";
matrixColor = LED_YELLOW;
}
else
matrixColor = LED_YELLOW;

matrix.setTextColor(matrixColor);

for (int8_t x=7; x>=-60; x--)


{
matrix.clear();
matrix.setCursor(x,0);
matrix.print(matrixComment);
matrix.writeDisplay();
delay(70);
}
}

PHPoC Shield source code

<!DOCTYPE html>
<html>
<head>
<title>PHPoC Shield - Snake Game</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7,
maximum-scale=0.7">
<style>
body { font-family: verdana, Helvetica, Arial, sans-serif, gulim; font-
weight: bold; text-align: center; }
h1 { font-size: 25pt; }
h2 { font-size: 15pt; }
#remote { margin:0 auto; width: 500px; background: #333; border-radius:
2%; }
.direct {
display: inline-block; width: 100px; height: 100px;
font-size: 50px; color: white; line-height: 90px;
background: #eee; margin: 8px; border-radius: 10%;
text-align: center; font-weight: bold;
margin: 10px 60px;
}
</style>
<script>
var ws;
var button;

function init()
{
if(ws == null)
{
ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?
>/snake", "text.phpoc");
document.getElementById("ws_state").innerHTML = "CONNECTING";

ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
}
else
ws.close();
}
function connect_onclick()
{
if(ws == null)
{
var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
//var debug = document.getElementById("debug");

if((navigator.platform.indexOf("Win") != -1) &&


(ws_host_addr.charAt(0) == "["))
{
// network resource identifier to UNC path name conversion
ws_host_addr = ws_host_addr.replace(/[\[\]]/g, '');
ws_host_addr = ws_host_addr.replace(/:/g, "-");
ws_host_addr += ".ipv6-literal.net";
}

//debug.innerHTML = "<br>" + navigator.platform + " " + ws_host_addr;


ws = new WebSocket("ws://" + ws_host_addr + "/snake", "text.phpoc");

document.getElementById("ws_state").innerHTML = "CONNECTING";

ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
}
else
ws.close();
}
function ws_onopen()
{
document.getElementById("ws_state").innerHTML = "<font
color='blue'>CONNECTED</font>";
document.getElementById("bt_connect").innerHTML = "Disconnect";
}
function ws_onclose()
{
document.getElementById("ws_state").innerHTML = "<font
color='gray'>CLOSED</font>";
document.getElementById("bt_connect").innerHTML = "Connect";

ws.onopen = null;
ws.onclose = null;
ws.onmessage = null;
ws = null;
}
function ws_onmessage(e_msg)
{
e_msg = e_msg || window.event; // MessageEvent

alert("msg : " + e_msg.data);


}

var beta = 0;
var gamma = 0;
var resolution = 2;

if (window.DeviceOrientationEvent)
{
window.addEventListener('deviceorientation', orientationUpdate, true);
}

function orientationUpdate(event)
{

if(Math.abs((event.beta - beta)) > resolution)


beta = event.beta;

if(Math.abs((event.gamma - gamma)) > resolution)


gamma = event.gamma;

//var debug = document.getElementById("debug");


//debug.innerHTML = beta + "/" + gamma;

for (i=0; i<4; i++)


{
button = document.getElementById(i);
button.style.backgroundColor = "grey";
}
if (beta < 0) // top
{
button = document.getElementById(0);
button.style.backgroundColor = "#E9FF26";
ws.send("0");
}
else if (gamma < -35 && beta < 50) // left
{
button = document.getElementById(1);
button.style.backgroundColor = "#E9FF26";
ws.send("1");
}
else if (gamma > 35 && beta < 50) // right
{
button = document.getElementById(2);
button.style.backgroundColor = "#E9FF26";
ws.send("2");
}
else if (beta > 60) // bottom
{
button = document.getElementById(3);
button.style.backgroundColor = "#E9FF26";
ws.send("3");
}

}
window.onload = init;
</script>
</head>

<body>
<h1>Snake Game</h1>
<br /><br />
<div id="remote">
<div class="direct" id="0">↑</div><br />
<div class="direct" id="1">←</div>
<div class="direct" id="2">→</div><br />
<div class="direct" id="3">↓</div>
</div>
<br /><br />
<h2>WebSocket <font id="ws_state" color="gray">CLOSED</font>
</h2>
<button id="bt_connect" type="button"
onclick="connect_onclick();">Connect</button>
<span id="debug"></span>
</body>
</html>
22) Arduino Eco Smart Container

COMPONENTS AND SUPPLIES

Arduino 101 & Genuino 101


× 1

SparkFun Inventor's Kit for


Arduino 101
× 1

Raspberry Pi Zero Wireless

× 1

DHT22 Temperature Sensor

× 1

Seeed Grove starter kit plus for


Intel Edison
× 1

Jumper wires (generic)

× 1

Ultrasonic Sensor - HC-SR04


(Generic)
× 1

SparkFun Soil Moisture Sensor


(with Screw Terminals)
× 1

Breadboard (generic)

× 1

Li-Ion Battery 1000mAh

× 1

USB-A to B Cable

× 1

USB-A to Micro-USB Cable

× 1
NECESSARY TOOLS AND MACHINES
Hot glue gun (generic)
APPS AND ONLINE SERVICES
Blynk

Arduino IDE

ABOUT THIS PROJECT


Material
1. SparkFun Inventor's Kit for Arduino 101
SparkFun Inventor's Kit for Arduino 101
This material was given to me by the sponsors of the contest, I thank
you for the trust and support. This material contains the plate you use
and the temperature sensor TMP36 that I use to measure the
temperature.
To test the circuits you were using, use the Arduino and Breadboard
Holder. The arduino 101.
2. Grove Shield
This shield is perfect for prototyping and connecting components
exclusive to the Grove platform.
3. Grove LCD I2C
This screen can be connected through the I2C port of the Arduino 101
and you can change the color of the lighting and it has a very nice
design.
4. Raspberry pi zero w

This board has all the advantages of raspberry pi zero but with the
addition of bluetooth 4.0 connectivity and wi-fi, use it to receive
arduino sensor values by means of bluetooth. Programming in Node Js
was a very enjoyable, intuitive and effective experience.
5. DHT22
This digital sensor of humidity and temperature is very used and has
good results, this one uses it to measure the temperature and humidity
near the central device that is the raspberry pi zero w.
6. Ultrasonic sensor
This sensor I used to measure the level of trash in the trash can, had
good results, but probably in an update can be changed by a sensor or
infrared sensor in my opinion seem more reliable but in my country it
is difficult to achieve components as sensors.
7. Moisture sensor
This sensor used it to measure the level of humidity in the earth, any
high reading of humidity means that there could be rain or some flood
and that could be a problem for the garbage of that place, sends a
warning to the application.
8. Solar battery bank
Any project needs power, my prototype I put this power bank of
12000mAh, which also recharges solar, ideally would have a panel
built especially for my prototype. But this device worked great. I used
2 for raspberry pi zero w and arduino 101 in my smart trash can.
9. Arduino 101 6-Axis Acelerometer and Gyroscope

To know if my trash can had fallen, or someone threw it on the floor.


Use the accelerometer and gyroscope included in the Arduino 101. It
was easy to implement and send the data to the central base.
Results
In the physical aspect of the prototype I will show some images and
explain the why of each thing. Below we have the top of the trash can
that has the LCD grove that has a nice message for people who use it
and leave their waste and also has as information the time and a word,
"ON" which means that the system is Connected to the central unit
which is the raspberry pi zero wy "OFF" means that it is disconnected.

Below is the finished prototype, on the outside only the LCD is visible
on the top and on the back you can see the power bank with its solar
panel, so this device is autonomous and sustainable with the
environment.

To prove that the arduino data was reaching the raspberry pi zero, I
made the latter by programming in node JS, print the value of each
sensor per console in Putty and below my results.
To implement the SMS notifications for my project I had to investigate
on the internet a lot and everything I gathered in the tutorial in which I
leave the link below.
https://www.hackster.io/alexis-santiago-allende/sms-alerts-for-arduino-
101-ble-e7184d
Also to connect arduino 101 with the raspberry pi zero w by bluetooth
of low energy carry out the following tutorial, in which I leave to
information that I found and as I did the process. In this final project
was to unite these two previous examples and make slight
modifications to obtain the desired operation.
https://www.hackster.io/alexis-santiago-allende/arduino-101-connects-
with-raspberry-pi-zero-w-63adc0
Blynk App
Below you can see how the application looks aesthetically, at the top of
the application you can see small boxes that are widgets, two of which
enable notifications, one of them is the one that activates the events of
the Blynk application and the Last is a bin viewer at the moment. In the
central part you can see 4 very beautiful displays of temperature and
humidity. One pair is from the arduino 101 and the other are from the
raspberry pi zero w, with my prototype you can add more visualization
widgets and more sensors but only use the ones that had available.
In the lower part you can see the trash level display next to 2 general
purpose buttons. That could be used to control any item at a distance as
lights from the central unit. The use of this hardware together with
Blynk gives many possibilities.

Notifications examples:
There are two types of notifications implemented, notifications specific
to the application and those that are through the Twilio SMS service.
Here below we have the temperature notification, when the temperature
is higher than a threshold, this sends a notification. In the project
notification is also given when the trash can is full.
Temperature notification
Notifications are also given when the central device is disconnected or
there is a connection failure.
Offline notifications
Apart from the notifications of the app, under the same cases, or if the
previous notifications do not work, we have the notifications by SMS
that in my opinion are more effective, below I leave the example of
when the trash can is full.
SMS notification

SCHEMATICS
CODE

Main code arduino

#include <CurieBLE.h>
#include "CurieIMU.h"
#include <Wire.h>
#include "rgb_lcd.h"
#include <CurieTime.h>

BLEPeripheral blePeripheral;//BLE Peripheral Device (Arduino Device)


BLEService demo111("19b10000-e8f2-537e4f6c-d104768a1214"); // BLE demo111 Service
// BLE sensor rate Characteristic"
BLEUnsignedIntCharacteristic sensor1("19b10001-e8f2-537e4f6c-d104768a1214",
BLERead | BLENotify);
// BLE sensor rate Characteristic"
BLEUnsignedIntCharacteristic sensor2("19b10002-e8f2-537e4f6c-d104768a1214",
BLERead | BLENotify);
// BLE sensor rate Characteristic"
BLEUnsignedIntCharacteristic sensor3("19b10003-e8f2-537e4f6c-d104768a1214",
BLERead | BLENotify);
// BLE sensor rate Characteristic"
BLEUnsignedIntCharacteristic sensor4("19b10004-e8f2-537e4f6c-d104768a1214",
BLERead | BLENotify);
//Ble palabra sensor Characteristic
BLECharacteristic palabra("19b10005-e8f2-537e4f6c-d104768a1214", BLERead |
BLENotify,10);
// BLE demo111 buttons Characteristic - custom 128-bit UUID, read and writable by central
BLEUnsignedCharCharacteristic buttons("19b10006-e8f2-537e4f6c-d104768a1214",
BLERead | BLEWrite);
rgb_lcd lcd;
const int colorR = 198;
const int colorG = 78;
const int colorB = 25;
int lastOrientation = - 1; // previous orientation (for comparison)
long previousMillis = 0; // last time the sensor was checked, in ms
const int green = 13; // pin to use for the green light
const int red = 11;// pin to use for the red light
boolean a = LOW, b = LOW; //Control variables
int temp=0;
long distancia;
long tiempo;
int orientation;
int valor=0,nivel=0,ndistancia;

void setup() {
Serial.begin(9600);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.setRGB(colorR, colorG, colorB);
// Print a message to the LCD.
setTime(16, 56, 24, 3, 07, 2017);
lcd.print("Have a nice day!");
lcd.setCursor(12, 1);
lcd.print("Off");
pinMode(green, OUTPUT); // use the LED on pin 13 as an output
pinMode(red, OUTPUT);
pinMode(9, OUTPUT); /*activación del pin 9 como salida: para el pulso ultrasónico*/
pinMode(8, INPUT);
CurieIMU.begin();
CurieIMU.setAccelerometerRange(2);
// set the local name peripheral advertises
blePeripheral.setLocalName("Demo111");
// set the UUID for the service this peripheral advertises
blePeripheral.setAdvertisedServiceUuid(demo111.uuid());

// add service and characteristic


blePeripheral.addAttribute(demo111);
blePeripheral.addAttribute(buttons);
blePeripheral.addAttribute(sensor1);
blePeripheral.addAttribute(sensor2);
blePeripheral.addAttribute(sensor3);
blePeripheral.addAttribute(sensor4);
blePeripheral.addAttribute(palabra);

// assign event handlers for connected, disconnected to peripheral


blePeripheral.setEventHandler(BLEConnected, blePeripheralConnectHandler);
blePeripheral.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);

// assign event handlers for characteristic


buttons.setEventHandler(BLEWritten, switchCharacteristicWritten);

// sensors.setEventHandler(BLEWritten, switchCharacteristicWritten);
// set an initial value for the characteristic
buttons.setValue(0);
sensor1.setValue(0);
sensor2.setValue(0);
sensor3.setValue(0);
sensor4.setValue(0);
// advertise the service
blePeripheral.begin();
Serial.println(("Bluetooth device active, waiting for connections..."));
}

void loop() {
// poll peripheral
blePeripheral.poll();
digitalWrite(9,LOW); /* Por cuestión de estabilización del sensor*/
delayMicroseconds(5);
digitalWrite(9, HIGH); /* envío del pulso ultrasónico*/
delayMicroseconds(10);
tiempo=pulseIn(8, HIGH); /* Función para medir la longitud del pulso entrante. Mide el
tiempo que transcurrido entre el envío
del pulso ultrasónico y cuando el sensor recibe el rebote, es decir: desde que el pin 12
empieza a recibir el rebote, HIGH, hasta que
deja de hacerlo, LOW, la longitud del pulso entrante*/
distancia= int(0.017*tiempo); /*fórmula para calcular la distancia obteniendo un valor
entero*/

char clockTime[8];
//use sprintf to create a time string of the hour, minte and seconds
sprintf(clockTime, "%02d:%02d:%02d", hour(), minute(), second());
//set cursor to column 0, row 0
lcd.setCursor(2, 1);
//print the date string over lcd
lcd.print(clockTime);

long currentMillis = millis();


// if 1s have passed, check the sensor:
if (currentMillis - previousMillis >= 1000) {
previousMillis = currentMillis;
updateSensor();
}

orientation = - 1; // the board's orientation


String orientationString; // string for printing description of orientation

// read accelerometer:
int x = CurieIMU.readAccelerometer(X_AXIS);
int y = CurieIMU.readAccelerometer(Y_AXIS);
int z = CurieIMU.readAccelerometer(Z_AXIS);

// calculate the absolute values, to determine the largest


int absX = abs(x);
int absY = abs(y);
int absZ = abs(z);

if ( (absZ > absX) && (absZ > absY)) {


// base orientation on Z
if (z > 0) {
orientationString = "up";
orientation = 0;
} else {
orientationString = "down";
orientation = 1;
}
} else if ( (absY > absX) && (absY > absZ)) {
// base orientation on Y
if (y > 0) {
orientationString = "digital pins up";
orientation = 2;
} else {
orientationString = "analog pins up";
orientation = 3;
}
} else {
// base orientation on X
if (x < 0) {
orientationString = "connector up";
orientation = 4;
} else {
orientationString = "connector down";
orientation = 5;
}
}

// if the orientation has changed, print out a description:


if (orientation != lastOrientation) {
Serial.println(orientationString);
lastOrientation = orientation;
}

void blePeripheralConnectHandler(BLECentral& central) {


// central connected event handler
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Have a nice day!");
Serial.print("Connected event, central: ");
Serial.println(central.address());
lcd.setCursor(12, 1);
lcd.print("On");
}

void blePeripheralDisconnectHandler(BLECentral& central) {


// central disconnected event handler
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Have a nice day!");
Serial.print("Disconnected event, central: ");
Serial.println(central.address());
lcd.setCursor(12, 1);
lcd.print("Off");
}

void switchCharacteristicWritten(BLECentral& central, BLECharacteristic& characteristic)


{
// central wrote new value to characteristic, update LED
Serial.print("Characteristic event, written: ");
Serial.print(buttons.value());
if (buttons.value() == 1 && a == LOW) { // 1 in ASCII

Serial.print("LED on");
digitalWrite(green, HIGH); // will turn the LED on
a = HIGH;
} else if (buttons.value() == 1 && a == HIGH) { //when 1 was read again (second time)

Serial.println("LED off");
digitalWrite(green, LOW); // will turn the LED off
a = LOW;
}
else if (buttons.value() == 2 && b == LOW) { // 1 in ASCII

Serial.print("LED on");
digitalWrite(red, HIGH); // will turn the LED on
b = HIGH;
} else if (buttons.value() == 2 && b == HIGH) { //when 1 was read again (second time)

Serial.println("LED off");
digitalWrite(red, LOW); // will turn the LED off
b = LOW;
}
}

void updateSensor() {
temp=analogRead(A0);//dht.readTemperature();//read temperature
valor=analogRead(A1);
nivel = map(valor, 0, 1023, 100, 0);
ndistancia = map(distancia, 38, 2, 0, 100);
float sensorLevel = temp*(3.3/1023);
int temp1=(sensorLevel-0.5)*100;
sensor1.setValue(temp1);//send temperature value
sensor2.setValue(distancia);//send distance value
sensor3.setValue(orientation);//send orientation value
sensor4.setValue(nivel);//send percentage of hummidity value
Serial.println(temp1);
Serial.println(distancia);
Serial.println(orientation);
Serial.println(nivel);

}
Main code Node JS

//Blynk
var Blynk = require('blynk-library');

var AUTH = 'adea86da8f774157b6a4997a6ed18a08';

var blynk = new Blynk.Blynk(AUTH);

var v1 = new blynk.VirtualPin(1);


var v9 = new blynk.VirtualPin(9);
var v8 = new blynk.VirtualPin(8);
var v7 = new blynk.VirtualPin(7);
var v6 = new blynk.VirtualPin(6);
var v5 = new blynk.VirtualPin(5);
var v4 = new blynk.VirtualPin(4);
var v3 = new blynk.VirtualPin(3);

//Bluetooth low energy


var noble = require('noble');

// Search only for the Service UUID of the device (remove dashes)
var serviceUuids = ['19b10000e8f2537e4f6cd104768a1214'];

// Search only for the led charateristic


var characteristicUuids =
['19b10001e8f2537e4f6cd104768a1214','19b10002e8f2537e4f6cd104768a1214','19b10

var sensor1=0;
var sensor2=0;
var sensor3=0;
var sensor4=0;
var temperatura=0;
var humedad=0;
var boton=0;
var contador1=0,contador2=0,contador3=0,contador4=0;

//Twilio
const twilio = require('twilio')
var accountSid = 'AC4c3a664e0475a08a4e0fdbd016555a70';
var authToken = '22ee6e5fe596967997a2d1a57d6d73eb';

const phone = new twilio(accountSid, authToken);

const sendMessage = () => {


phone.messages.create({
to: "+526462378678",
from: "+12818266123 ",
body: 'WARNING!!!!!! take care, please review your Blynk app now!!!!!',
})
}
//Reading DHT22
var sensor = require('node-dht-sensor');

//Final
v1.on('write', function(param) {
boton=param[0];

});

v9.on('read', function() {
v9.write(new Date().getSeconds());
});

v8.on('read', function() {
v8.write(sensor1);
});

v7.on('read', function() {
v7.write(humedad);
});

v6.on('read', function() {
v6.write(temperatura);
});

v5.on('read', function() {
v5.write(sensor2);
});

v4.on('read', function() {
v4.write(sensor3);
});

v4.on('read', function() {
v4.write(sensor4);
});

// start scanning when bluetooth is powered on


noble.on('stateChange', function(state) {
if (state === 'poweredOn') {
noble.startScanning(serviceUuids);
} else {
noble.stopScanning();
}
});
//Reading sensor
setInterval(function() {
sensor.read(22, 21, function(err, temperature, humidity) {
if (!err) {
temperatura=temperature.toFixed(1);
humedad= humidity.toFixed(1);

}
});
}, 1000);

// Search for BLE peripherals


noble.on('discover', function(peripheral) {
peripheral.connect(function(error) {
console.log('connected to peripheral: ' + peripheral.uuid);
// Only discover the service we specified above
peripheral.discoverServices(serviceUuids, function(error, services) {
var service = services[0];
console.log('discovered service');

service.discoverCharacteristics(characteristicUuids, function(error,
characteristics) {
console.log('discovered characteristics');
// Assign Characteristic
var sensor1Characteristic = characteristics[1];
var sensor2Characteristic = characteristics[2];
var sensor3Characteristic = characteristics[3];
var sensor4Characteristic = characteristics[4];
//var botonCharacteristic = characteristics[4];

setInterval(function() {
sensor1Characteristic.read(function(error, data) {
// data is a buffer
console.log('Temperature is: ' + data.readUInt8(0));
sensor1=data.readUInt8(0);
if (data.readUInt8(0)>=32 && contador1===0) {
sendMessage();
contador1=1;
}
else if(data.readUInt8(0)<=30 && contador1==1){
contador1=0;

});

sensor2Characteristic.read(function(error, data) {
// data is a buffer
console.log('Trash percent is: ' + data.readUInt8(0));
sensor2=data.readUInt8(0);
if (data.readUInt8(0)<=4 && contador2===0) {
sendMessage();
contador2=1;
}
else if(data.readUInt8(0)>=30 && contador2==1){
contador2=0;

}
});

sensor3Characteristic.read(function(error, data) {
// data is a buffer
console.log('Orientation: ' + data.readUInt8(0));
sensor3=data.readUInt8(0);
if (data.readUInt8(0)!=2 && contador3===0) {
sendMessage();
contador3=1;
}
else if(data.readUInt8(0)==2 && contador3==1){
contador3=0;

}
});

sensor4Characteristic.read(function(error, data) {
// data is a buffer
console.log('Humidity: ' + data.readUInt8(0));
sensor4=data.readUInt8(0);
if (data.readUInt8(0)>=90 && contador4===0) {
sendMessage();
contador4=1;
}
else if(data.readUInt8(0)<=30 && contador4==1){
contador4=0;

}
});

}, 1000);

// var bufferToSend = new Buffer(1);


// bufferToSend.writeUInt8(boton);
// console.log(bufferToSend);
// botonCharacteristic.write(bufferToSend, false);
// setInterval(function() {
//bufferToSend.writeUInt8(1); // you can pass this any integer, we just do
this to alternate 0/1
// botonCharacteristic.write(bufferToSend, false);
// }, 1000);
});
});
});
});
23) Arduino Without External Clock Ctystal on Atmega328

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO
To program the ATmega chip on
the breadboard. You can use FTDI × 1
Breakout Board also.

Microchip Atmega328
× 1

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

SparkFun FTDI 232RL USB to


Serial Converter
× 1
If not using Arduino Uno, then,
use this.
Capacitor 100 nF
To be used if using FTDI USB to
× 1
Serial Breakout.
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


An Arduino consists of many components like: a linear regulator, USB
to Serial microcontroller, debug LED, power LED, reset button, RX &
TX LED, crystal oscillator, etc. But a minimal circuit can have just the
brain of the Arduino UNO, that is, an ATmega328p microcontroller
(Reducing Arduino Power Consumption). You can assume this one is
an extended version of that project.
Making a Minimal Arduino UNO on a Breadboard
Most people are successful in making Arduino with minimal circuitry,
but use the 16 MHz crystal. We can remove that, too, along with 22 pF
capacitors. You can configure the ATmega328 to use its internal 8 MHz
RC oscillator as a clock source.
Install Support for Hardware Configuration
Download this hardware configuration archive: breadboard-1-6-
x.zip, Breadboard1-5-x.zip or Breadboard1-0-x.zip depending on
which IDE you use.
Create a "hardware" sub-folder in your Arduino sketchbook
folder (whose location you can find in the Arduino preferences
dialog). If you've previously installed support for additional
hardware configuration, you may already have a "hardware" folder
in your sketchbook.
Move the breadboard folder from the zip archive to the "hardware"
folder of your Arduino sketchbook.
Restart the Arduino software.
You should see "ATmega328 on a breadboard (8 MHz internal
clock)" in the Tools > Board menu.
Once you've done this, you can burn the bootloader and upload
programs onto your ATmega328.
Putting Stuff on Breadboard
Get all the stuff listed above. Moreover, keep a pin mapping of the
ATmega328P handy while making the circuit.

ATmega328p pin mapping.


Using ATmega Without UNO Bootloader
First of all, we need to burn the bootloader to the ATmega chip if you
bought a blank microcontroller having no bootloader, so that it can be a
programmable entity.
Refer to the schematics and place the ATmega chip in the
breadboard.
Open the ArduinoISP firmware (in Examples) to your Arduino
board.
Select the items in the Tools > Board and Serial Port menus that
correspond to the board you are using as the programmer (not the
board being programmed).
Upload the ArduinoISP sketch.
Select the item in the Tools > Board menu and be sure to select
"ATmega328 on a breadboard (8MHz internal clock)" when burning
the bootloader.
Select the Arduino as ISP in the Tools > Programmer menu.
Use the Burn Boot-loader command in the Tools menu.
Skip step 2 if you have done step 1.
2. Using ATmega with UNO boot-loader
If the ATmega is already boot-loaded, then just put it in the breadboard
and we can proceed programming the ATmega328p microcontroller.
3. Programming the ATmega chip (using other Arduino)
Remove the microcontroller of the Arduino you are using as the
programmer.
Refer to the schematics and pin mapping and connect
the Rx and Tx of programmer Arduino to Tx and Rx of
the breadboard Arduino respectively.
Connect RESET of programmer Arduino to RESET of breadboard
Arduino.
Connect GND and VCC of breadboard
Arduino to GND and VCC on programmer Arduino.
Select the item in the Tools > Board menu and be sure to select
"ATmega328 on a breadboard (8MHz internal clock)".
Check the port and click on "upload".
Plug out the connections and now you can power it with a battery for
months depending on the kind of project.
4. Programming the ATmega chip (using FTDI USB to Serial Adapter)
Curious what all the pin outs are for on the FT232RL breakout board?
Simply flip it over! In this situation I'll be using VCC (to supply 5V
from the USB port to your board), GND, TXD, and RXD. [Refer to
schematics]

FTDI 232RL Breakout board pinouts.


This board comes without the headers when bought from market. So,
solder the male header and plug it in the breadboard.
Connect Rx of ATmega chip to Tx of board and Tx of ATmega chip
to Rx of the board.
Connect Vcc and GND to the power rails on the breadboard.
Plug the USB mini type - B and connect it with your computer and
upload the sketch using the Arduino IDE but always remember to
select "ATmega328 on a breadboard (8MHz internal clock)". It will
take power from the USB but after disconnecting the USB, you can
plug the battery terminals to the power rails of breadboard.
And the Arduino is ready.

SCHEMATICS

Using an Arduino board to burn the bootloader onto an ATmega on a


breadboard (w/o an external clock)
Uploading sketches to an ATmega on a breadboard(using another
Arduino).

Uploading sketches to an ATmega on a breadboard(using FTDI 232RL


Driver)
Ignore the capacitors(except 10nF cap), resistors and the clock crystal.
CODE

// This sketch turns the Arduino into a AVRISP


// using the following arduino pins:
//
// Pin 10 is used to reset the target microcontroller.
//
// By default, the hardware SPI pins MISO, MOSI and SCK pins are used
// to communicate with the target. On all Arduinos, these pins can be
found
// on the ICSP/SPI header:
//
// MISO . . 5V (!) Avoid this pin on Due, Zero...
// SCK . . MOSI
// . . GND
//
// On some Arduinos (Uno,...), pins MOSI, MISO and SCK are the same
pins
// as digital pin 11, 12 and 13, respectively. That is why many tutorials
// instruct you to hook up the target to these pins. If you find this wiring
// more practical, have a define USE_OLD_STYLE_WIRING. This will
work even
// even when not using an Uno. (On an Uno this is not needed).
//
// Alternatively you can use any other digital pin by configuring software
('BitBanged')
// SPI and having appropriate defines for PIN_MOSI, PIN_MISO and
PIN_SCK.
//
// IMPORTANT: When using an Arduino that is not 5V tolerant (Due,
Zero, ...)
// as the programmer, make sure to not expose any of the programmer's
pins to 5V.
// A simple way to accomplish this is to power the complete system
(programmer
// and target) at 3V3.
//
// Put an LED (with resistor) on the following pins:
// 9: Heartbeat - shows the programmer is running
// 8: Error - Lights up if something goes wrong (use red if that makes
sense)
// 7: Programming - In communication with the slave
//

#include "Arduino.h"
#undef SERIAL

#define PROG_FLICKER true

// Configure SPI clock (in Hz).


// E.g. for an attiny @128 kHz: the datasheet states that both the high
// and low spi clock pulse must be > 2 cpu cycles, so take 3 cycles i.e.
// divide target f_cpu by 6:
// #define SPI_CLOCK (128000/6)
//
// A clock slow enough for an attiny85 @ 1MHz, is a reasonable default:

#define SPI_CLOCK (1000000/6)

// Select hardware or software SPI, depending on SPI clock.


// Currently only for AVR, for other archs (Due, Zero,...),
// hardware SPI is probably too fast anyway.

#if defined(ARDUINO_ARCH_AVR)

#if SPI_CLOCK > (F_CPU / 128)


#define USE_HARDWARE_SPI
#endif

#endif

// Configure which pins to use:

// The standard pin configuration.


#ifndef ARDUINO_HOODLOADER2

#define RESET 10 // Use pin 10 to reset the target rather than SS


#define LED_HB 9
#define LED_ERR 8
#define LED_PMODE 7

// Uncomment following line to use the old Uno style wiring


// (using pin 11, 12 and 13 instead of the SPI header) on Leonardo, Due...
// #define USE_OLD_STYLE_WIRING

#ifdef USE_OLD_STYLE_WIRING

#define PIN_MOSI 11
#define PIN_MISO 12
#define PIN_SCK 13

#endif

// HOODLOADER2 means running sketches on the atmega16u2


// serial converter chips on Uno or Mega boards.
// We must use pins that are broken out:
#else

#define RESET 4
#define LED_HB 7
#define LED_ERR 6
#define LED_PMODE 5

#endif

// By default, use hardware SPI pins:


#ifndef PIN_MOSI
#define PIN_MOSI MOSI
#endif

#ifndef PIN_MISO
#define PIN_MISO MISO
#endif

#ifndef PIN_SCK
#define PIN_SCK SCK
#endif

// Force bitbanged SPI if not using the hardware SPI pins:


#if (PIN_MISO != MISO) || (PIN_MOSI != MOSI) || (PIN_SCK != SCK)
#undef USE_HARDWARE_SPI
#endif

// Configure the serial port to use.


//
// Prefer the USB virtual serial port (aka. native USB port), if the Arduino
has one:
// - it does not autoreset (except for the magic baud rate of 1200).
// - it is more reliable because of USB handshaking.
//
// Leonardo and similar have an USB virtual serial port: 'Serial'.
// Due and Zero have an USB virtual serial port: 'SerialUSB'.
//
// On the Due and Zero, 'Serial' can be used too, provided you disable
autoreset.
// To use 'Serial': #define SERIAL Serial

#ifdef SERIAL_PORT_USBVIRTUAL
#define SERIAL SERIAL_PORT_USBVIRTUAL
#else
#define SERIAL Serial
#endif

// Configure the baud rate:

#define BAUDRATE 19200


// #define BAUDRATE 115200
// #define BAUDRATE 1000000
#define HWVER 2
#define SWMAJ 1
#define SWMIN 18

// STK Definitions
#define STK_OK 0x10
#define STK_FAILED 0x11
#define STK_UNKNOWN 0x12
#define STK_INSYNC 0x14
#define STK_NOSYNC 0x15
#define CRC_EOP 0x20 //ok it is a space...

void pulse(int pin, int times);

#ifdef USE_HARDWARE_SPI
#include "SPI.h"
#else

#define SPI_MODE0 0x00

class SPISettings {
public:
// clock is in Hz
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) :
clock(clock){
(void) bitOrder;
(void) dataMode;
};

private:
uint32_t clock;
friend class BitBangedSPI;
};

class BitBangedSPI {
public:
void begin() {
digitalWrite(PIN_SCK, LOW);
digitalWrite(PIN_MOSI, LOW);
pinMode(PIN_SCK, OUTPUT);
pinMode(PIN_MOSI, OUTPUT);
pinMode(PIN_MISO, INPUT);
}

void beginTransaction(SPISettings settings) {


pulseWidth = (500000 + settings.clock - 1) / settings.clock;
if (pulseWidth == 0)
pulseWidth = 1;
}

void end() {}

uint8_t transfer (uint8_t b) {


for (unsigned int i = 0; i < 8; ++i) {
digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH : LOW);
digitalWrite(PIN_SCK, HIGH);
delayMicroseconds(pulseWidth);
b = (b << 1) | digitalRead(PIN_MISO);
digitalWrite(PIN_SCK, LOW); // slow pulse
delayMicroseconds(pulseWidth);
}
return b;
}

private:
unsigned long pulseWidth; // in microseconds
};

static BitBangedSPI SPI;

#endif

void setup() {
SERIAL.begin(BAUDRATE);

pinMode(LED_PMODE, OUTPUT);
pulse(LED_PMODE, 2);
pinMode(LED_ERR, OUTPUT);
pulse(LED_ERR, 2);
pinMode(LED_HB, OUTPUT);
pulse(LED_HB, 2);

int error = 0;
int pmode = 0;
// address for reading and writing, set by 'U' command
unsigned int here;
uint8_t buff[256]; // global block storage

#define beget16(addr) (*addr * 256 + *(addr+1) )


typedef struct param {
uint8_t devicecode;
uint8_t revision;
uint8_t progtype;
uint8_t parmode;
uint8_t polling;
uint8_t selftimed;
uint8_t lockbytes;
uint8_t fusebytes;
uint8_t flashpoll;
uint16_t eeprompoll;
uint16_t pagesize;
uint16_t eepromsize;
uint32_t flashsize;
}
parameter;

parameter param;

// this provides a heartbeat on pin 9, so you can tell the software is


running.
uint8_t hbval = 128;
int8_t hbdelta = 8;
void heartbeat() {
static unsigned long last_time = 0;
unsigned long now = millis();
if ((now - last_time) < 40)
return;
last_time = now;
if (hbval > 192) hbdelta = -hbdelta;
if (hbval < 32) hbdelta = -hbdelta;
hbval += hbdelta;
analogWrite(LED_HB, hbval);
}

static bool rst_active_high;

void reset_target(bool reset) {


digitalWrite(RESET, ((reset && rst_active_high) || (!reset &&
!rst_active_high)) ? HIGH : LOW);
}
void loop(void) {
// is pmode active?
if (pmode) {
digitalWrite(LED_PMODE, HIGH);
} else {
digitalWrite(LED_PMODE, LOW);
}
// is there an error?
if (error) {
digitalWrite(LED_ERR, HIGH);
} else {
digitalWrite(LED_ERR, LOW);
}

// light the heartbeat LED


heartbeat();
if (SERIAL.available()) {
avrisp();
}
}

uint8_t getch() {
while (!SERIAL.available());
return SERIAL.read();
}
void fill(int n) {
for (int x = 0; x < n; x++) {
buff[x] = getch();
}
}

#define PTIME 30
void pulse(int pin, int times) {
do {
digitalWrite(pin, HIGH);
delay(PTIME);
digitalWrite(pin, LOW);
delay(PTIME);
} while (times--);
}

void prog_lamp(int state) {


if (PROG_FLICKER) {
digitalWrite(LED_PMODE, state);
}
}

uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {


SPI.transfer(a);
SPI.transfer(b);
SPI.transfer(c);
return SPI.transfer(d);
}

void empty_reply() {
if (CRC_EOP == getch()) {
SERIAL.print((char)STK_INSYNC);
SERIAL.print((char)STK_OK);
} else {
error++;
SERIAL.print((char)STK_NOSYNC);
}
}

void breply(uint8_t b) {
if (CRC_EOP == getch()) {
SERIAL.print((char)STK_INSYNC);
SERIAL.print((char)b);
SERIAL.print((char)STK_OK);
} else {
error++;
SERIAL.print((char)STK_NOSYNC);
}
}

void get_version(uint8_t c) {
switch (c) {
case 0x80:
breply(HWVER);
break;
case 0x81:
breply(SWMAJ);
break;
case 0x82:
breply(SWMIN);
break;
case 0x93:
breply('S'); // serial programmer
break;
default:
breply(0);
}
}

void set_parameters() {
// call this after reading paramter packet into buff[]
param.devicecode = buff[0];
param.revision = buff[1];
param.progtype = buff[2];
param.parmode = buff[3];
param.polling = buff[4];
param.selftimed = buff[5];
param.lockbytes = buff[6];
param.fusebytes = buff[7];
param.flashpoll = buff[8];
// ignore buff[9] (= buff[8])
// following are 16 bits (big endian)
param.eeprompoll = beget16(&buff[10]);
param.pagesize = beget16(&buff[12]);
param.eepromsize = beget16(&buff[14]);

// 32 bits flashsize (big endian)


param.flashsize = buff[16] * 0x01000000
+ buff[17] * 0x00010000
+ buff[18] * 0x00000100
+ buff[19];

// avr devices have active low reset, at89sx are active high
rst_active_high = (param.devicecode >= 0xe0);
}

void start_pmode() {

// Reset target before driving PIN_SCK or PIN_MOSI

// SPI.begin() will configure SS as output,


// so SPI master mode is selected.
// We have defined RESET as pin 10,
// which for many arduino's is not the SS pin.
// So we have to configure RESET as output here,
// (reset_target() first sets the correct level)
reset_target(true);
pinMode(RESET, OUTPUT);
SPI.begin();
SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST,
SPI_MODE0));
// See avr datasheets, chapter "SERIAL_PRG Programming Algorithm":

// Pulse RESET after PIN_SCK is low:


digitalWrite(PIN_SCK, LOW);
delay(20); // discharge PIN_SCK, value arbitrally chosen
reset_target(false);
// Pulse must be minimum 2 target CPU clock cycles
// so 100 usec is ok for CPU speeds above 20KHz
delayMicroseconds(100);
reset_target(true);

// Send the enable programming command:


delay(50); // datasheet: must be > 20 msec
spi_transaction(0xAC, 0x53, 0x00, 0x00);
pmode = 1;
}

void end_pmode() {
SPI.end();
// We're about to take the target out of reset
// so configure SPI pins as input
pinMode(PIN_MOSI, INPUT);
pinMode(PIN_SCK, INPUT);
reset_target(false);
pinMode(RESET, INPUT);
pmode = 0;
}

void universal() {
uint8_t ch;

fill(4);
ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
breply(ch);
}

void flash(uint8_t hilo, unsigned int addr, uint8_t data) {


spi_transaction(0x40 + 8 * hilo,
addr >> 8 & 0xFF,
addr & 0xFF,
data);
}
void commit(unsigned int addr) {
if (PROG_FLICKER) {
prog_lamp(LOW);
}
spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
if (PROG_FLICKER) {
delay(PTIME);
prog_lamp(HIGH);
}
}

unsigned int current_page() {


if (param.pagesize == 32) {
return here & 0xFFFFFFF0;
}
if (param.pagesize == 64) {
return here & 0xFFFFFFE0;
}
if (param.pagesize == 128) {
return here & 0xFFFFFFC0;
}
if (param.pagesize == 256) {
return here & 0xFFFFFF80;
}
return here;
}

void write_flash(int length) {


fill(length);
if (CRC_EOP == getch()) {
SERIAL.print((char) STK_INSYNC);
SERIAL.print((char) write_flash_pages(length));
} else {
error++;
SERIAL.print((char) STK_NOSYNC);
}
}

uint8_t write_flash_pages(int length) {


int x = 0;
unsigned int page = current_page();
while (x < length) {
if (page != current_page()) {
commit(page);
page = current_page();
}
flash(LOW, here, buff[x++]);
flash(HIGH, here, buff[x++]);
here++;
}

commit(page);

return STK_OK;
}

#define EECHUNK (32)


uint8_t write_eeprom(unsigned int length) {
// here is a word address, get the byte address
unsigned int start = here * 2;
unsigned int remaining = length;
if (length > param.eepromsize) {
error++;
return STK_FAILED;
}
while (remaining > EECHUNK) {
write_eeprom_chunk(start, EECHUNK);
start += EECHUNK;
remaining -= EECHUNK;
}
write_eeprom_chunk(start, remaining);
return STK_OK;
}
// write (length) bytes, (start) is a byte address
uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) {
// this writes byte-by-byte,
// page writing may be faster (4 bytes at a time)
fill(length);
prog_lamp(LOW);
for (unsigned int x = 0; x < length; x++) {
unsigned int addr = start + x;
spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]);
delay(45);
}
prog_lamp(HIGH);
return STK_OK;
}

void program_page() {
char result = (char) STK_FAILED;
unsigned int length = 256 * getch();
length += getch();
char memtype = getch();
// flash memory @here, (length) bytes
if (memtype == 'F') {
write_flash(length);
return;
}
if (memtype == 'E') {
result = (char)write_eeprom(length);
if (CRC_EOP == getch()) {
SERIAL.print((char) STK_INSYNC);
SERIAL.print(result);
} else {
error++;
SERIAL.print((char) STK_NOSYNC);
}
return;
}
SERIAL.print((char)STK_FAILED);
return;
}

uint8_t flash_read(uint8_t hilo, unsigned int addr) {


return spi_transaction(0x20 + hilo * 8,
(addr >> 8) & 0xFF,
addr & 0xFF,
0);
}

char flash_read_page(int length) {


for (int x = 0; x < length; x += 2) {
uint8_t low = flash_read(LOW, here);
SERIAL.print((char) low);
uint8_t high = flash_read(HIGH, here);
SERIAL.print((char) high);
here++;
}
return STK_OK;
}

char eeprom_read_page(int length) {


// here again we have a word address
int start = here * 2;
for (int x = 0; x < length; x++) {
int addr = start + x;
uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF,
0xFF);
SERIAL.print((char) ee);
}
return STK_OK;
}

void read_page() {
char result = (char)STK_FAILED;
int length = 256 * getch();
length += getch();
char memtype = getch();
if (CRC_EOP != getch()) {
error++;
SERIAL.print((char) STK_NOSYNC);
return;
}
SERIAL.print((char) STK_INSYNC);
if (memtype == 'F') result = flash_read_page(length);
if (memtype == 'E') result = eeprom_read_page(length);
SERIAL.print(result);
}

void read_signature() {
if (CRC_EOP != getch()) {
error++;
SERIAL.print((char) STK_NOSYNC);
return;
}
SERIAL.print((char) STK_INSYNC);
uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
SERIAL.print((char) high);
uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
SERIAL.print((char) middle);
uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
SERIAL.print((char) low);
SERIAL.print((char) STK_OK);
}
//////////////////////////////////////////
//////////////////////////////////////////

////////////////////////////////////
////////////////////////////////////
void avrisp() {
uint8_t ch = getch();
switch (ch) {
case '0': // signon
error = 0;
empty_reply();
break;
case '1':
if (getch() == CRC_EOP) {
SERIAL.print((char) STK_INSYNC);
SERIAL.print("AVR ISP");
SERIAL.print((char) STK_OK);
}
else {
error++;
SERIAL.print((char) STK_NOSYNC);
}
break;
case 'A':
get_version(getch());
break;
case 'B':
fill(20);
set_parameters();
empty_reply();
break;
case 'E': // extended parameters - ignore for now
fill(5);
empty_reply();
break;
case 'P':
if (!pmode)
start_pmode();
empty_reply();
break;
case 'U': // set address (word)
here = getch();
here += 256 * getch();
empty_reply();
break;

case 0x60: //STK_PROG_FLASH


getch(); // low addr
getch(); // high addr
empty_reply();
break;
case 0x61: //STK_PROG_DATA
getch(); // data
empty_reply();
break;

case 0x64: //STK_PROG_PAGE


program_page();
break;

case 0x74: //STK_READ_PAGE 't'


read_page();
break;

case 'V': //0x56


universal();
break;
case 'Q': //0x51
error = 0;
end_pmode();
empty_reply();
break;

case 0x75: //STK_READ_SIGN 'u'


read_signature();
break;

// expecting a command, not CRC_EOP


// this is how we can get back in sync
case CRC_EOP:
error++;
SERIAL.print((char) STK_NOSYNC);
break;

// anything else we will return STK_UNKNOWN


default:
error++;
if (CRC_EOP == getch())
SERIAL.print((char)STK_UNKNOWN);
else
SERIAL.print((char)STK_NOSYNC);
}
}

24) Arduino Sun Tracking Solar System


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Analog Devices LDR Sensor


× 1

Solderless Breadboard Full Size

× 1
solar panel
× 1

SG90 Micro-servo motor

× 2

Jumper wires (generic)

× 1

Resistor 1k ohm

× 4
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


It seems you can'twalk down the street these days without coming across a
solar panel. You canfind them for mobile charging in rural areas, as well
as simple little sidewalkpath lights. Solar is easy to use, readily available,
and inexpensive.
Every panel you seein your day to day life is in a fixed position. While this
approach isextremely simple and meets the needs of most small
applications, it isn'tproducing as much energy as it could be.
Our tracker isa dual axis tracker , meaningit tracks in both X and Y. To
put it into even more simple terms, it goes left, right, up, and down. This
means once you have your tracker set up you willnever need to change or
adjust anything, since anywhere the sun moves yourtracker will follow.
SCHEMATICS
CODE

#include<Servo.h> // library for servo motor

Servo s; // define Vertival servo


Servo sh; // define horizontal servo
int start1 = 90; // initially starting from 90 degree
int start2 = 90;
int L1 = A0; //for read data from LDR1
int L2 = A1; //for read data from LDR2
int L3 = A2; //for read data from LDR3
int L4 = A3; //for read data from LDR4
int a = 15;

void setup()
{
s.attach(9); //connect vertical servo to pin 9 of arduino
sh.attach(10); //connect horizontal servo to pin 10 of arduino
pinMode(L1, INPUT); //define LDR as input
pinMode(L2, INPUT);
pinMode(L3, INPUT);
pinMode(L4, INPUT);
s.write(start1); //it will start servo from 90 when we reset system
sh.write(start2);
delay(2000);
}
void loop()
{
int LDR1 = analogRead(L1); //read value from LDR
int LDR2 = analogRead(L2);
int LDR3 = analogRead(L3);
int LDR4 = analogRead(L4);
int plus14 =(LDR1+LDR4); //average of two corner LDR
int plus23 =(LDR2+LDR3);
int plus12 =(LDR1+LDR2);
int plus34 =(LDR3+LDR4);
int diff1= abs(plus14 - plus23); // difference to take proper value
int diff2= abs(plus23 - plus14);
int diff3= abs(plus12 - plus34);
int diff4= abs(plus34 - plus12);

if((diff1 <= a) || (diff2 <= a))


{
//difference is less then 15 so do nothing
}
else
{
if(plus14 > plus23) //move vertical servo in lessthen 90 degree
{
start2= --start2;
}
if(plus14 < plus23)
{
start2 = ++start2; //move vertical servo in greaterthen 90 degree
}
}
if(plus12 > plus34 )
{
start1= --start1; // move horizontal servo in lessthen 90 degree
}
if(plus12 < plus34)
{
start1= ++start1; //move horizontal servo in greaterthen 90 degree
}
s.write(start1);
sh.write(start2);
delay(100);
}
25) Arduino Max 30102 Heart Rate Monitor on LCD
COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

MAX 30102 Heart rate monitor


× 1

Adafruit RGB Backlight LCD -


16x2
× 1
Rotary potentiometer (generic)

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


This is a simple heart rate monitor made with a MAX30102 sensor
module. I wrote a simple code based on Arduino libraries and values
are shown on a 16x2 LCD screen. The first row displays averge beats
per minute, and the second row shows the value of the reflected
infrared beam. This value should be constant to make readings more
accurate.Our tracker isa dual axis tracker, meaningit tracks in both X and
Y. To put it into even more simple terms, it goes left, right, up, and down.
This means once you have your tracker set up you willnever need to
change or adjust anything, since anywhere the sun moves yourtracker will
follow.
SCHEMATICS
CODE

/*
Optical Heart Rate Detection (PBA Algorithm) using the MAX30105 Breakout

This is a demo to show the reading of heart rate or beats per minute (BPM) using
a Penpheral Beat Amplitude (PBA) algorithm.

It is best to attach the sensor to your finger using a rubber band or other tightening
device. Humans are generally bad at applying constant pressure to a thing. When you
press your finger against the sensor it varies enough to cause the blood in your
finger to flow differently which causes the sensor readings to go wonky.

Hardware Connections (Breakoutboard to Arduino):


-5V = 5V (3.3V is allowed)
-GND = GND
-SDA = A4 (or SDA)
-SCL = A5 (or SCL)
-INT = Not connected

The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the
board with 5V
but it will also run at 3.3V.
*/

#include <Wire.h>
#include "MAX30105.h"
#include <LiquidCrystal.h>

#include "heartRate.h"

MAX30105 particleSensor;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.


byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

void setup()
{
Serial.begin(9600);

lcd.begin(16, 2);
Serial.println("Initializing...");

// Initialize sensor
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
{
Serial.println("MAX30105 was not found. Please check wiring/power. ");
while (1);
}
Serial.println("Place your index finger on the sensor with steady pressure.");

particleSensor.setup(); //Configure sensor with default settings


particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is
running
particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
}

void loop()
{
long irValue = particleSensor.getIR();

if (checkForBeat(irValue) == true)
{
//We sensed a beat!
long delta = millis() - lastBeat;
lastBeat = millis();

beatsPerMinute = 60 / (delta / 1000.0);

if (beatsPerMinute < 255 && beatsPerMinute > 20)


{
rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
rateSpot %= RATE_SIZE; //Wrap variable

//Take average of readings


beatAvg = 0;
for (byte x = 0 ; x < RATE_SIZE ; x++)
beatAvg += rates[x];
beatAvg /= RATE_SIZE;
}
}

Serial.print("IR=");
Serial.print(irValue);
Serial.print(", BPM=");
Serial.print(beatsPerMinute);
Serial.print(", Avg BPM=");
Serial.print(beatAvg);

if (irValue < 50000)


Serial.print(" No finger?");

Serial.println();

lcd.setCursor(0,0);
lcd.print("BPM: ");
lcd.print(beatAvg);

lcd.setCursor(0,1);
lcd.print(" IR: ");
lcd.print(irValue);
}
26) Rainfall Measured Using Arduino

COMPONENTS AND SUPPLIES

water sensor
× 1

Arduino UNO & Genuino UNO

× 1
ABOUT THIS PROJECT
SCHEMATICS
CODE

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup () {
// initialize serial communication at 9600 bits per second:
Serial.begin (9600);}
void loop() {
// read the input on analog pin 0:
int value = analogRead(A0);
lcd.setCursor(0, 7);
if (value > 500) {
Serial.println("Very heavy Rain");
lcd.print("Very heavy rain");}
else if ((value > 300) && (value <= 500)) {
Serial.println("AVERAGE Rain");
lcd.print("Average Rain");
lcd.print(" "); }
else{
Serial.println("Dry Weather");
lcd.print("Dry Wather");
lcd.print(" ");}
delay(100);}

27) Arduino Touchless Mouse


COMPONENTS AND SUPPLIES
Bitcraze Flow breakout

× 1

Arduino Leonardo

× 1

ABOUT THIS PROJECT

This project implements a touchless mouse.


The Bitcraze flow breakout contains an optical flow sensor that is able
to sense how things are moving in front of it and a ranging sensor to
sense the distance to the nearest object. The flow sensor is essentially
an optical mouse sensor fitted with a lens focused to track objects far
away.
The touchless mouse can detect that a hand is approaching and detect
how it is moving, the movements are translated into mouse movements
by an Arduino.
By using an Arduino Leonardo (or any other USB device-compatible
Arduino) this project is seen as a regular mouse so it works out of the
box on any computer.
Hardware setup

The flow deck is connected to two busses of the Arduino:


The PMW3901 optical tracking sensor is connected to the SPI bus
The VL53 ranging sensor is connected to the i2C bus
We also need to power the flow deck, this is done by connecting it to
the 5V and GND pin of the Arduino. Note that on Arduino Leonardo,
the SPI bus is only accessible on the ICSP pin header.
Required library
The two sensors require libraries to work. Using the Arduino IDE
Library manager we load the two libraries:
VL53L0x for the ranging sensor
Bitcraze_pmw3901 for the optical flow sensor

When an object is detected by the ranging sensor, at a distance between


80mm and 200mm, the movement measured by the flow sensor is sent
as mouse movement. When the detected object is below 50mm we
press the mouse button. The reason to keep 50mm to 80mm without
motion detection and click is to make sure that the mouse is clicking
without any movement: without this gap the mouse was always moving
a bit when the hand goes down to click.
SCHEMATICS
CODE

#include "Bitcraze_PMW3901.h"
#include <Wire.h>
#include <VL53L0X.h>
#include <Mouse.h>

VL53L0X rangeSensor;

// Using digital pin 10 for chip select


Bitcraze_PMW3901 flow(10);

void setup() {
Serial.begin(9600);
// Initialize flow sensor
if (!flow.begin()) {
Serial.println("Initialization of the flow sensor failed");
while(1) { }
}
// Initialize range sensor
Wire.begin();
rangeSensor.init();
rangeSensor.setTimeout(500);
// Initialize Mouse
Mouse.begin();
}
int16_t deltaX,deltaY;

void loop() {
// Get motion count since last call
flow.readMotionCount(&deltaX, &deltaY);
// Get single range measurement
float range = rangeSensor.readRangeSingleMillimeters();

// Send motion as mouse movement when the hand is between 80 and 200mm
if (range < 200 && range > 80) {
Mouse.move(deltaX, -deltaY, 0);
}

// Press the left mouse button when the hand is bellow 50mm
if (range < 50) {
Mouse.press();
} else {
Mouse.release();
}
}
28) Arduino Ankle Air Guitar Pedal
COMPONENTS AND SUPPLIES

Arduino Nano R3
any arduino is okay, im thinking on using
tinyduino × 1

mpc41010
× 1
digital potenciometer
SparkFun Triple Axis Accelerometer Breakout
- ADXL335
any analogoutput accelerometer is okay × 1
stereo audio jack 6,5 mm female adapter
× 1

stereo audio jack 6,5 mm cable


× 1

RGB Diffused Common Cathode


just for fun, no needed
× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


We need to weld the correct things, so follow along. The current
interest in dubstep was growing, and I was ready to spend 40€ on one
expression pedal for my boss synthesizer when I remembered I was an
electronics nerd.
Then science occurred.
At first, I thought about drilling a shoe and gluing the electronics
inside, but I did not have a pair of shoes to spare. So, I ended up
purchasing a hair band and stitching thread.
First steps with the MPC digital potentiometers family:
We have a lot of types to choose from, but I picked this one - the
MPC41010.
MPC41010: single potentiometer, 10k ohm
MPC41050: single potentiometer, 50k ohm
MPC41100: single potentiometer, 100k ohm
MCP42010: two independent potentiometers, 10k ohm
MCP42050: two independent potentiometers, 50k ohm
MCP42100: two independent potentiometers, 100k ohm
More things about them here. Important things that you need to know
for hacking this device:
You can do similar things with other digital potentiometers. (like the
COM-10613, more info)
The resistance is 0 to 10k ohms divided in 255 steps with each step
of 39 ohms. (MATH!)
Serial communication: just use #include <SPI.h>.

What I learned with the prototype:


When the device is reset, the human needs to set the flat and the top
values for adjusting the range of movement.
It would be nice to implement a function that chooses between the
axis which had the wider range of variation. This would be useful so
that you don't have to mind the position of the accelerometer; you could
put it in upside-down, on the bass top, on your wrist, etc.
Maybe I need to implement a logarithmic behaviour for the resistance
values.
I need to take care of the 0 level because it is highly instable.
Building the stereo jack 6,5 mm cable
Keep in mind I am poor. So for 4€, I bought the components (couple of
male jack endings and 1 meter of cable).
We need to weld the correct things, so follow the scheme and use
some hot-shrink tube to do a fine job.
SCHEMATICS
CODE
#include <SPI.h>
#define debug //comment this line if you´re not gonna use the serial data with the arduino
ide

#define CS 10 //chipselect

#define accelerometerX A0//analogpins for the accelerometer


#define accelerometerY A1
#define accelerometerZ A2

#define RED 6 //rgb pins


#define GREEN 3
#define BLUE 5

//MCP41010 chip´s connection


// 39ohms per step of the
//CS 10 U vcc
//SCK 13 serial clock PBO--UPRESISTOR
//SI 11 serial imput PWO INRESISTOR
//gnd PAO--BOTTOMRESISTOR

int datarray[18]={0,0,0,0,0,0,1023,1023,1023,0,0,0,0,0,0};
int smoothingarray[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int rgb[3];
int i=0,chipvalue=0;
int ResistorValue=0;
void setup() {
//
//pinMode (GREEN, OUTPUT);//GREEN RGB (PWM)
//pinMode (BLUE, OUTPUT);//BLUE
//pinMode (RED, OUTPUT);//RED
//digitalWrite(GREEN, HIGH);//setting the led off at the begining
//digitalWrite (BLUE, HIGH);//
//digitalWrite (RED, HIGH);//

pinMode (CS, OUTPUT);//chipselect for the MCP41010 chip


pinMode (13, OUTPUT);//things are happening led
pinMode (accelerometerX, INPUT);//acelerometer´s inputs
pinMode (accelerometerY, INPUT);//
pinMode (accelerometerZ, INPUT);//
SPI.begin();
MCP41010Write(0);//init value horizontal foot

#ifdef debug
Serial.begin(9600);
#endif
}

void loop() {
datarray[0]=analogRead(accelerometerX);
datarray[1]=analogRead(accelerometerY);
datarray[2]=analogRead(accelerometerZ);

comparemaxmin(datarray);

detectRange(datarray);

ResistorValue=map(datarray[datarray[15]],datarray[datarray[15]+6]+20,datarray[datarray[15
to the min and -10 to the max for preventing unreachable edges

chipvalue =constrain(ResistorValue,0,255);

MCP41010Write(smoothing(chipvalue));

// //map(value, fromLow, fromHigh, toLow, toHigh)


// for(i=0;i<=2;i++){
// rgb[i]=map(datarray[i],datarray[i+6],datarray[i+3],0,255);
// }
////analogWrite(GREEN, rgb[0]);//EL LED DA PROBLEMAS DE LECTURA
ruido/////////////////////7
////analogWrite (BLUE, rgb[1]);//
////analogWrite (RED, rgb[2]);//

#ifdef debug
Serial.print("//RawReadings: ");
Serial.print(datarray[0]);
Serial.print(" ");
Serial.print(datarray[1]);
Serial.print(" ");
Serial.print(datarray[2]);

Serial.print(" /max ");


Serial.print(datarray[3]);
Serial.print(" ");
Serial.print(datarray[4]);
Serial.print(" ");
Serial.print(datarray[5]);

Serial.print(" /min ");


Serial.print(datarray[6]);
Serial.print(" ");
Serial.print(datarray[7]);
Serial.print(" ");
Serial.print(datarray[8]);

Serial.print(" //GAP :");


Serial.print(datarray[9]);
Serial.print(" ");
Serial.print(datarray[10]);
Serial.print(" ");
Serial.print(datarray[11]);

// Serial.print("/?? ");
// Serial.print(datarray[12]);
// Serial.print(" ");
// Serial.print(datarray[13]);
// Serial.print(" ");
// Serial.print(datarray[14]);

Serial.print(" //axis choose ");


Serial.print(datarray[15]);

Serial.print(" //chip value ");


Serial.print(chipvalue);

Serial.println();
#endif
delay(100);//delay for stability
}

void comparemaxmin(int datarray[])


{
for(i=0;i<=2;i++)
datarray[i+3]=max(datarray[i],datarray[i+3]);

for(i=0;i<=2;i++)
datarray[i+6]=min(datarray[i],datarray[i+6]);

void detectRange(int datarray[18])


{
for(i=0;i<=2;i++)
{
datarray[i+9]=abs(abs(datarray[i+3])-abs(datarray[i+6]));
}
if(datarray[9]>=datarray[10]&&datarray[9]>=datarray[11])//choosing the axis with the
wider range
datarray[15]=0;
if(datarray[10]>=datarray[9]&&datarray[10]>=datarray[11])
datarray[15]=1;
if(datarray[11]>=datarray[9]&&datarray[11]>=datarray[10])
datarray[15]=2;
}

void MCP41010Write(byte value) //speaking protocol with the mcp chip


{
// Note that the integer value passed to this subroutine
// is cast to a byte

digitalWrite(CS,LOW);
SPI.transfer(B00010001); // This tells the chip to set the pot
SPI.transfer(value); // This tells it the pot position
digitalWrite(CS,HIGH);
}

int smoothing(int data){


int result,j;

for(j=0;j<=14;j++){
smoothingarray[j] = smoothingarray[j+1];
}
smoothingarray[14]= data;

result=
(smoothingarray[0]+smoothingarray[1]+smoothingarray[2]+smoothingarray[3]+smoothingarray
constrain(result,0,255);
return result;
}

29) Arduino Word Clock


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO


any microcontroller will do
× 1

Real Time Clock (RTC)

× 1
Texas Instruments 74hc595
× 1
shift register
STMicroelectronics uln2803a
× 1
darlington array
led strip
× 1

ic holders 16pin x3 and 18pin x3


× 1

12v power supply


× 1
NECESSARY TOOLS AND MACHINES
mount board

acrylic board
APPS AND ONLINE SERVICES
Arduino IDE

rtc library

ABOUT THIS PROJECT


Introduction
All you need is an arduino and a RTC. I have removed the switches and
other hardware. Since DS1307 is pretty stable, it does not require
frequent time changes! It will also keep the time even if there is a
power failure, thanks to its internal 3v battery. This battery will last for
years.
So even if you are going on a vacation, just turn off the clock and the
time will be running accurate when you turn it back on!
I have made the code as simple as possible! It just reads time from the
RTC and updates the shift registers.
Step 1: Collecting the Parts –
ELECTRONICS COMPONENTS USED
Main parts
Arduino or just atmega328p as i have used (standalone) x1
RTC (Real Time Clock) DS1307 x1
Shift registers 74hc595 x3
ULN2803a Darlington Transistor Arrays as LED drivers x3
LED strip I have used white...approx 2m
16 pin IC socket x3
18 pin IC socket x3
12v power source may be battery or wall adapter
Miscellaneous
Proto board / general PCB board
Connecting wires
Male header pins
Jumper wires- female-female
basic soldering
FRAME AND STENCIL
Mount board / thick cardboard
Glue, Tape
Scissors, Paper cutter
Acrylic Board (translucent white) / Plexi glass
Snickering of Words
Step 2: Making the Connections....
Follow the simple circuit diagram shown above.
I have used a standalone arduino which I can program with FTDI
cables, but any arduino board can be used !!For this project even
though we control 22 individual LED arrays, we just use 5 I/O pins
from the arduino ie.- 3 for shift Registors and 2 for RTC module.
Using shift resistors is a great way to increase the i/o pins.
Important thing about ULN2803a Drivers -
This IC is a darlington pair.
Hence connect all the cathodes [positive terminals] of the LEDs to the
source and the anodes [negative/ground] to the respective output
terminals of the driver!
Step 3: Building the Frame
Here I have used mount board for the construction...
It is easy to cut, bend and handle the mount board. It is also has less
strength.
Any material like wood, plastic, metal etc. can be used.
Cut a piece of mount board the size of the front Board with words.
Make a rough sketch of the words and their alignment on the board.
Cut strips of mount board of size may be 1.5 cm.. This is to make
compartments, the size of the words. this will prevent the light from
one word to diffuse and illuminate the surrounding words.
Place the strips horizontally after each line of words and vertically in
between the words; make small boxes for each of the word.
Finally make a box that will sneakily fit the electronics, the LED
board, anti-diffusion boxes and the outermost board with words
stickered on to it.
Step 4: Connecting the LEDs
I'm using the LED strip in this project. It is easy to operate. It can be
cut for desired length, no need of soldering each and every led to make
an array. LED Strips also come with a peel-off sticker at the back.
Just cut the required length of the strip depending on the size of the
word and stick it on the LED board ( mount board). Remember that
most of the led strips have connectors at an interval of 3 LEDs. So you
have to cut at the indicated points only. Therefore even the smallest
word will have 3 LEDs.
You can even use the standard LEDs, solder them for desired number
of LEDs. Remember to use the resistor for each array that you make.
the value of the resistor depends on the specifications of the LEDs
used. You can check here for further info, LED calc or this one.
Connect all the Positive terminals of the LED strip together. This is the
common Vcc for the leds.
You can see that i have connected it using thin copper wire. Then
Connect wires for all the individual ground terminals for each word
and bring it back to connect it to the driver.
Step 5: The Codes
The original code itself is well commented and easily understandable.
The #define section allots the pins on the shift register for individual
words. They will be updated each time when the time changes.
The void WriteLEDs function updates the shift regesters through the data
pin.
The void self-test function blinks all the LED words in a sequence so that you know
everything is working correctly. i.e. for troubleshooting.
The void displaytime function will check the time with the RTC chip and see which
words to be illuminated accordingly.
The rest can be easily made out by the code itself.
GitHub

Step 6: Finishing It Off.


Place all the controller boards; arduino and circuit which contains shift
registers, RTC chip and LED drivers.
Connect the LED arrays of each word to the respective pin of the
driver.
Place the LED board inside the casing and fix it in place...
The main outer stencil is made by sticking the words onto any
acrylic or plastic.
Make a hole at the back for fixing the clock for using a nail.

SCHEMATICS
CODE

/*

RTClib information---
SDA pin -----> A4 / D18
SCL pin -----> A5 / D19
*/
#include <string.h>
#include <Wire.h>
#include"RTClib.h"

// Display output pin assignments


#define MINUTES Display1=Display1 | B00000001
#define MTEN Display1=Display1 | B00000010
#define HALF Display1=Display1 | B00000100
#define PAST Display1=Display1 | B00001000
#define THREE Display1=Display1 | B00010000
#define ITIS Display1=Display1 | B00100000
#define TWENTY Display1=Display1 | B01000000
#define TO Display1=Display1 | B10000000

#define TWO Display2=Display2 | B00000001


#define SIX Display2=Display2 | B00000010
#define TWELVE Display2=Display2 | B00000100
#define HFIVE Display2=Display2 | B00001000
#define SEVEN Display2=Display2 | B00010000
#define OCLOCK Display2=Display2 | B00100000
#define ONE Display2=Display2 | B01000000
#define QUARTER Display2=Display2 | B10000000

#define EIGHT Display3=Display3 | B00000001


#define MFIVE Display3=Display3 | B00000010
#define ARDUINO Display3=Display3 | B00000100
#define ELEVEN Display3=Display3 | B00001000
#define HTEN Display3=Display3 | B00010000
#define NINE Display3=Display3 | B00100000
#define FOUR Display3=Display3 | B01000000
#define RBK Display3=Display3 | B10000000

int hour=0, minute=0, second=0;


static unsigned long msTick =0; // the number of Millisecond Ticks since we last
// incremented the second counter
int selftestmode; // 1 = in self test - flash display
char Display1=0, Display2=0, Display3=0;

// hardware constants
int LEDClockPin=8; // Arduino Pin#8 - Shift register 74HC595 Pin 11 clock
int LEDDataPin=9; // Arduino Pin#9 - Shift register 74HC595 pin 14 Data
int LEDLatchPin=10; // Arduino Pin#10 - Shift register 74HC595 pin 12 Latch

// RTC DEFINE-
RTC_DS1307 RTC ;

void setup()
{
// initialise the hardware
// initialize the appropriate pins as outputs:
pinMode(LEDClockPin, OUTPUT);
pinMode(LEDDataPin, OUTPUT);
pinMode(LEDLatchPin, OUTPUT);

Serial.begin(9600); // setup the serial port to 9600 baud


Wire.begin();
RTC.begin();

// test whether the DS1307 is there


Serial.print("Verifying DS1307 ");

if ( RTC.isrunning()) {
Serial.println("RTC is running.....");
DateTime now = RTC.now();

Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
}

DateTime now = RTC.now();

msTick=millis(); // Initialise the msTick counter

selftest(); // validate the hardware for the user

selftestmode=0;

if ( RTC.isrunning() ) {
// Get the current time and date from the RTC chip

second=now.second();
minute=now.minute();
hour=now.hour();
}

displaytime(); // display the current time


}

void WriteLEDs(){
// Now we write the actual values to the hardware
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display3);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display2);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display1);
digitalWrite(LEDLatchPin,HIGH);
//delay(2);
digitalWrite(LEDLatchPin,LOW);

}
void ledsoff(void) {
Display1=0;
Display2=0;
Display3=0;

void selftest(void){
// start by clearing the display to a known state
ledsoff();
ITIS;
WriteLEDs();
delay(500);
ledsoff();
MTEN;
WriteLEDs();
delay(500);
ledsoff();
HALF;
WriteLEDs();
delay(500);
ledsoff();
TWENTY;
WriteLEDs();
delay(500);
ledsoff();
QUARTER;
WriteLEDs();
delay(500);
ledsoff();
MFIVE;
WriteLEDs();
delay(500);
ledsoff();
MINUTES;
WriteLEDs();
delay(500);
ledsoff();
PAST;
WriteLEDs();
delay(500);
ledsoff();
TO;
WriteLEDs();
delay(500);
ledsoff();
ONE;
WriteLEDs();
delay(500);
ledsoff();
TWO;
WriteLEDs();
delay(500);
ledsoff();
THREE;
WriteLEDs();
delay(500);
ledsoff();
FOUR;
WriteLEDs();
delay(500);
ledsoff();
HFIVE;
WriteLEDs();
delay(500);
ledsoff();
SIX;
WriteLEDs();
delay(500);
ledsoff();
SEVEN;
WriteLEDs();
delay(500);
ledsoff();
EIGHT;
WriteLEDs();
delay(500);
ledsoff();
NINE;
WriteLEDs();
delay(500);
ledsoff();
HTEN;
WriteLEDs();
delay(500);
ledsoff();
ELEVEN;
WriteLEDs();
delay(500);
ledsoff();
TWELVE;
WriteLEDs();
delay(500);
ledsoff();
OCLOCK;
WriteLEDs();
delay(500);
ledsoff();
RBK;
WriteLEDs();
delay(500);
ledsoff();
ARDUINO;
WriteLEDs();
delay(500);
ledsoff();

for(int i=0; i<5; i++)


{
Display1=255;
Display2=255;
Display3=255;
WriteLEDs();
delay(500);
ledsoff();
WriteLEDs();
delay(500);
}

void displaytime(void){

// start by clearing the display to a known state


ledsoff();

// Now, turn on the "It is" leds


ITIS;
Serial.print("It is ");

// now we display the appropriate minute counter


if ((minute>4) && (minute<10)) {
MFIVE;
MINUTES;
Serial.print("Five Minutes ");
}
if ((minute>9) && (minute<15)) {
MTEN;
MINUTES;
Serial.print("Ten Minutes ");
}
if ((minute>14) && (minute<20)) {
QUARTER;
Serial.print("Quarter ");
}
if ((minute>19) && (minute<25)) {
TWENTY;
MINUTES;
Serial.print("Twenty Minutes ");
}
if ((minute>24) && (minute<30)) {
TWENTY;
MFIVE;
MINUTES;
Serial.print("Twenty Five Minutes ");
}
if ((minute>29) && (minute<35)) {
HALF;
Serial.print("Half ");
}
if ((minute>34) && (minute<40)) {
TWENTY;
MFIVE;
MINUTES;
Serial.print("Twenty Five Minutes ");
}
if ((minute>39) && (minute<45)) {
TWENTY;
MINUTES;
Serial.print("Twenty Minutes ");
}
if ((minute>44) && (minute<50)) {
QUARTER;
Serial.print("Quarter ");
}
if ((minute>49) && (minute<55)) {
MTEN;
MINUTES;
Serial.print("Ten Minutes ");
}
if (minute>54) {
MFIVE;
MINUTES;
Serial.print("Five Minutes ");
}

if ((minute <5))
{
switch (hour) {
case 1:
case 13:
ONE;
Serial.print("One ");
break;
case 2:
case 14:
TWO;
Serial.print("Two ");
break;
case 3:
case 15:
THREE;
Serial.print("Three ");
break;
case 4:
case 16:
FOUR;
Serial.print("Four ");
break;
case 5:
case 17:
HFIVE;
Serial.print("Five ");
break;
case 6:
case 18:
SIX;
Serial.print("Six ");
break;
case 7:
case 19:
SEVEN;
Serial.print("Seven ");
break;
case 8:
case 20:
EIGHT;
Serial.print("Eight ");
break;
case 9:
case 21:
NINE;
Serial.print("Nine ");
break;
case 10:
case 22:
HTEN;
Serial.print("Ten ");
break;
case 11:
case 23:
ELEVEN;
Serial.print("Eleven ");
break;
case 0:
case 12:
TWELVE;
Serial.print("Twelve ");
break;
}
OCLOCK;
Serial.println("O'Clock");
}
else
if ((minute < 35) && (minute >4))
{
PAST;
Serial.print("Past ");
switch (hour) {
case 1:
case 13:
ONE;
Serial.println("One ");
break;
case 2:
case 14:
TWO;
Serial.println("Two ");
break;
case 3:
case 15:
THREE;
Serial.println("Three ");
break;
case 4:
case 16:
FOUR;
Serial.println("Four ");
break;
case 5:
case 17:
HFIVE;
Serial.println("Five ");
break;
case 6:
case 18:
SIX;
Serial.println("Six ");
break;
case 7:
case 19:
SEVEN;
Serial.println("Seven ");
break;
case 8:
case 20:
EIGHT;
Serial.println("Eight ");
break;
case 9:
case 21:
NINE;
Serial.println("Nine ");
break;
case 10:
case 22:
HTEN;
Serial.println("Ten ");
break;
case 11:
case 23:
ELEVEN;
Serial.println("Eleven ");
break;
case 0:
case 12:
TWELVE;
Serial.println("Twelve ");
break;
}
}
else
{
// if we are greater than 34 minutes past the hour then display
// the next hour, as we will be displaying a 'to' sign
TO;
Serial.print("To ");
switch (hour) {
case 1:
case 13:
TWO;
Serial.println("Two ");
break;
case 14:
case 2:
THREE;
Serial.println("Three ");
break;
case 15:
case 3:
FOUR;
Serial.println("Four ");
break;
case 4:
case 16:
HFIVE;
Serial.println("Five ");
break;
case 5:
case 17:
SIX;
Serial.println("Six ");
break;
case 6:
case 18:
SEVEN;
Serial.println("Seven ");
break;
case 7:
case 19:
EIGHT;
Serial.println("Eight ");
break;
case 8:
case 20:
NINE;
Serial.println("Nine ");
break;
case 9:
case 21:
HTEN;
Serial.println("Ten ");
break;
case 10:
case 22:
ELEVEN;
Serial.println("Eleven ");
break;
case 11:
case 23:
TWELVE;
Serial.println("Twelve ");
break;
case 0:
case 12:
ONE;
Serial.println("One ");
break;
}
}

void loop()
{
DateTime now = RTC.now();

second=now.second();
minute=now.minute();
hour=now.hour();

//Serial.println("Loop Started");
// Flash the onboard Pin13 Led every 5 sec so we know something is hapening!
if ( millis() - msTick >5000) {
msTick=millis();

digitalWrite(13,HIGH);
delay(50);
digitalWrite(13,LOW);
delay(50);
digitalWrite(13,HIGH);
delay(50);
digitalWrite(13,LOW);

Serial.print(second);
Serial.print("..");
}

if (second==59) // Update the display every 1 minute...


{
displaytime();
WriteLEDs();
}

30) Arduino Traffic Advisor


COMPONENTS AND SUPPLIES
Arduino Nano R3

× 1

3 mm LED: Yellow

× 8

3 mm LED: Green

× 1
Pushbutton Switch, Momentary
4 pin, small generaic push button
× 6

Resistor 220 ohm

× 6

Hook Up Wire Kit, 22 AWG

× 1

ControlEverything.com Relay
Shield for Particle Photon I²C 8-
Channel SPDT 10-Amp × 1

Adafruit NeoPixel Digital RGB


LED Strip 144 LED, 1m White
× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Solder Wire, Lead Free

Wire Stripper & Cutter, 18-10 AWG / 0.75-


4mm² Capacity Wires

ABOUT THIS PROJECT


I wanted to see how hard it would be to make this.
this is a traffic advisor controller.
it controls 8 light segments and has a small led readout to show you
what pattern is currently being used.
a power light to show that power is on.
6 buttons that do various actions
button 1: left arrow
button 2: center out
button 3: right arrow
button 4: warning patterns
button 5: switch warning pattern
button 6: turn off lights/ save warning pattern
there are the 3 directional patterns and 10 warning patterns.
any mode can be activated at any time with no delay.
warning patterns are:
1:even / odd fast flash
2: half and half
3: half and half with fast flash
4: 2 by 2
5: 2 by 2 parallel
6: out flash
7: 3 out center
8: outboard
9:inboard
10: even / odd slow
SCHEMATICS
CODE

#include <EEPROM.h>
int warning_button = A5;
int left_button = 2;
int center_button = 4;
int right_button = 3;
int off_button = A0;
int pattern_button = A2;
int statuslight = 13;
int LEDright[] = {5, 6, 7, 8, 9, 10, 11, 12};
int LEDleft[] = {12, 11, 10, 9, 8, 7, 6, 5};
int centerleft[] = {9, 10, 11, 12};
int centerright[] = {8, 7, 6, 5};
int light = 0;
int counter = 1;
int pattern_count = 0;
int warning_count = EEPROM.read(0);
long lasttimer = 0;
static long timer = 200;
static long timer2 = 300;
static long switch_timer = 4000;
#define LEFTside 0x0
#define RIGHTside 0x1
byte whichLED = LEFTside;
byte LEFT_state = LOW;
byte RIGHT_state = LOW;
unsigned long switchDelay = 1000;
unsigned long switchDelay2 = 500;
unsigned long strobeDelay = 75;
unsigned long strobeWait = strobeDelay;
unsigned long waitUntilSwitch = switchDelay;
unsigned long sequenceStartTime;
//----------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
for (int i = 0; i < 8; i++) {
pinMode(LEDright[i], OUTPUT);
}
pinMode(statuslight, OUTPUT);
pinMode(warning_button, INPUT_PULLUP);
pinMode(left_button, INPUT_PULLUP);
pinMode(center_button, INPUT_PULLUP);
pinMode(right_button, INPUT_PULLUP);
pinMode(off_button, INPUT_PULLUP);
pinMode(pattern_button, INPUT_PULLUP);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
}
//------------------------------------------------------------------------
void loop() {
digitalWrite(13, HIGH);
delayMicroseconds(10); // Approximately 10% duty cycle @ 1KHz
digitalWrite(13, LOW);
delayMicroseconds(1000 - 10);
if (digitalRead(pattern_button) == HIGH)
{
delay(500);
warning_count++;
if (warning_count > 10) {
warning_count = 1;
}
}
if (digitalRead(warning_button) == HIGH)
{
delay(50);
pattern_count = 1;
}
if (digitalRead(left_button) == HIGH)
{
delay(50);
pattern_count = 2;
}
if (digitalRead(center_button) == HIGH)
{
delay(50);
pattern_count = 3;
}
if (digitalRead(right_button) == HIGH)
{
delay(50);
pattern_count = 4;
}
if (digitalRead(off_button) == HIGH)
{
delay(50);
pattern_count = 0;
EEPROM.update(0,warning_count);
}
switch (pattern_count) {
case 0:
pattern_off();
break;
case 1:
traffic_left();
break;
case 2:
traffic_center();
break;
case 3:
traffic_right();
break;
case 4:
traffic_warning();
break;
}
}
void pattern_off() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
}
void traffic_left() {
unsigned long currenttimer = millis();
if (currenttimer - lasttimer >= timer) {
lasttimer = currenttimer;
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
digitalWrite(LEDleft[light], LOW);
light = light + counter;
if (light > 7) {
light = 0;
counter = 1;
}
digitalWrite(LEDleft[light], HIGH);
}
}
void traffic_center() {
unsigned long currenttimer = millis();
if (currenttimer - lasttimer >= timer2) {
lasttimer = currenttimer;
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
digitalWrite(centerright[light], LOW);
digitalWrite(centerleft[light], LOW);
light = light + counter;
if (light > 3) {
light = 0;
counter = 1;
}
digitalWrite(centerright[light], HIGH);
digitalWrite(centerleft[light], HIGH);
}
}
void traffic_right() {
unsigned long currenttimer = millis();
if (currenttimer - lasttimer >= timer) {
lasttimer = currenttimer;
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
digitalWrite(LEDright[light], LOW);
light = light + counter;
if (light > 7) {
light = 0;
counter = 1;
}
digitalWrite(LEDright[light], HIGH);
}
}
void traffic_warning() {
switch (warning_count) {
case 1:
even_odd_flash();
break;
case 2:
half_half();
break;
case 3:
half_half_flash();
break;
case 4:
two_by_two();
break;
case 5:
two_by_two_parallel();
break;
case 6:
out_flash();
break;
case 7:
one_center();
break;
case 8:
outboard();
break;
case 9:
inboard();
break;
case 10:
even_odd();
break;
}
}
void even_odd_flash() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
digitalWrite(12, LEFT_state);
digitalWrite(11, RIGHT_state);
digitalWrite(10, LEFT_state);
digitalWrite(9, RIGHT_state);
digitalWrite(8, LEFT_state);
digitalWrite(7, RIGHT_state);
digitalWrite(6, LEFT_state);
digitalWrite(5, RIGHT_state);
if ((long)(millis() - waitUntilSwitch) >= 0) {
LEFT_state = LOW;
RIGHT_state = LOW;
whichLED = !whichLED;
waitUntilSwitch += switchDelay;
}
if ((long)(millis() - strobeWait) >= 0) {
if (whichLED == LEFTside)
LEFT_state = !LEFT_state;
if (whichLED == RIGHTside)
RIGHT_state = !RIGHT_state;
strobeWait += strobeDelay;
}
}
void half_half_flash() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
digitalWrite(12, LEFT_state);
digitalWrite(11, LEFT_state);
digitalWrite(10, LEFT_state);
digitalWrite(9, LEFT_state);
digitalWrite(8, RIGHT_state);
digitalWrite(7, RIGHT_state);
digitalWrite(6, RIGHT_state);
digitalWrite(5, RIGHT_state);
if ((long)(millis() - waitUntilSwitch) >= 0) {
LEFT_state = LOW;
RIGHT_state = LOW;
whichLED = !whichLED;
waitUntilSwitch += switchDelay2;
}
if ((long)(millis() - strobeWait) >= 0) {
if (whichLED == LEFTside)
LEFT_state = !LEFT_state;
if (whichLED == RIGHTside)
RIGHT_state = !RIGHT_state;
strobeWait += strobeDelay;
}
}
void half_half() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 250)
{
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
else if (time < 500)
{
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(10, LOW);
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
digitalWrite(7, HIGH);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
}
else sequenceStartTime = millis();
}
void out_flash() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 150)
{
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, LOW);
digitalWrite(9, LOW);
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
}
else if (time < 300)
{
digitalWrite(12, LOW);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, LOW);
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
digitalWrite(6, HIGH);
digitalWrite(5, LOW);
}
else sequenceStartTime = millis();
}
void two_by_two() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 150)
{
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, LOW);
digitalWrite(9, LOW);
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
}
else if (time < 300)
{
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
digitalWrite(8, HIGH);
digitalWrite(7, HIGH);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
else sequenceStartTime = millis();
}
void two_by_two_parallel() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 150)
{
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, LOW);
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
digitalWrite(7, HIGH);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
else if (time < 300)
{
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
}
else sequenceStartTime = millis();
}
void one_center() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 500)
{
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
else if (time < 1000)
{
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(10, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
}
else sequenceStartTime = millis();
}
void outboard() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 200)
{
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
}
else if (time < 400)
{
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(6, HIGH);
digitalWrite(5, HIGH);
}
else sequenceStartTime = millis();
}
void inboard() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 200)
{
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, LOW);
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
digitalWrite(6, HIGH);
}
else if (time < 400)
{
digitalWrite(11, LOW);
digitalWrite(10, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
}
else sequenceStartTime = millis();
}
void even_odd() {
for (int i = 0; i <= 7; i++) {
digitalWrite(LEDright[i], LOW);
}
long time = millis() - sequenceStartTime;
if (time < 300)
{
digitalWrite(12, HIGH);
digitalWrite(11, LOW);
digitalWrite(10, HIGH);
digitalWrite(9, LOW);
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
digitalWrite(6, HIGH);
digitalWrite(5, LOW);
}
else if (time < 600)
{
digitalWrite(12, LOW);
digitalWrite(11, HIGH);
digitalWrite(10, LOW);
digitalWrite(9, HIGH);
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
digitalWrite(6, LOW);
digitalWrite(5, HIGH);
}
else sequenceStartTime = millis();
}
31) Arduino Word Clock on 8X8 RGB LED Matrix
COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

Full-color RGB 8x8 LED+Colorful


Magic Matrix Driver shield
Colorduino KIT DIY × 1

Maxim Integrated DS1307 64 x 8,


Serial, I²C Real-Time Clock
× 1

SparkFun Pushbutton switch 12mm

× 2

Photo resistor

× 1

Rotary potentiometer (generic)

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Full-color RGB 8x8 LED+Colorful Magic Matrix Driver shield
Colorduino KIT DIY" which is also known as Funduino, consists of the
8x8 RGB LED matrix and driver shield (control board with atmega
chip and LED drivers).

This is probably the best project that can be done with this module.
There are many projects on the Internet that are just pattern generators
and nothing more.
Mark Wilson made an intuitive word clock, and even wrote his own
library "chromaduino" which you can find at GitHub:
https://github.com/funnypolynomial/Chromaduino
It drives the LEDs and receives display information from a master over
I2C.
Now I will try to explain step by step the construction of this device.
First, you have to program the control board. For this purpose we take
Arduino Uno, from which we extract the Atmega chip, and connect
with the control board in the following way:
GND-GND, 5V-VCC, RX(D0)-RXD, TX(D1)-TXD and RESET-DTR
(Arduino-Control board)

In Arduino IDE we choose the appropriate serial port and Duemilanove


board and upload chromaduino.ino library. This will program the
ATmega on the Funduino/Colorduino board. The matrix is placed on
the control board in a way that pin 1 on the matrix goes to Blue pin 1
on the board.
Next, we need to program the Arduino Nano (master) board, and on it,
through the I2C protocol connect Colorduino and DS3231 Real-time
clock module as described in the scheme below. There are also two
buttons ("Adj" and "Set") connected to the analog inputs A2 and A3
that are used to set the clock:
- Pressing Adj cycles through color modes: RGB, reds, greens, blues,
white(ish) and random. Unless the current time is on the hour, in which
case it toggles showing NONE/EVEN
- Pressing and holding Set sets the display dimming, first the ambient
level to "DIM AT" then the brightness to "DIM TO"
- Pressing Set and Adj cycles through display off and alternate faces
- Holding Set at power on runs the LED matrix demo
- Holding Adj at power on runs the clock in demo mode
- Holding Set and Adj at power on resets the clock configuration
The clock contains two Clock faces. The first face ("Half Ten") shows
the time as MINUTES TO HOUR or MINUTES OF HOUR, for
example, FIFTEEN TO TEN (at 9:45) or FIFTEEN OF TEN (at 10:15).
The second face ("Ten Thirty") simply shows the time as HOUR
MINUTES, for example, TEN FIFTEEN (at 10:15).
I made the letter plates at a local graphic design company where I
printed faces on a transparent plastic plate, and for better visibility, I
put a sheet of white paper between a plastic grid and a letter plate. I
have printed the plastic grid on my 3D printer.
SCHEMATICS
CODE

#include "arduino.h"
#include <avr/pgmspace.h>
#include <Wire.h>
#include <EEPROM.h>
#include "PINS.h"
#include "RTC.h"
#include "LDR.h"
#include "LEDS.h"
#include "BTN.h"
#include "CFG.h"
#include "CLK.h"

/*
A "word clock" showing the time on one of two 8x8 character grids:
TWENONTY or THRTWONE
FIFVTEEN TWELEVEN
HALFMTOF ENEIGHTI
FOURFIVE SIXSEVEN
SIXSEVEN FOURFIVE
EIGHTHRI THIRTWEN
TWELEVEN MFIFORTY
ONETWOEE EFIVTEEN

Driving an 8x8 RGB LED matrix.


Mark Wilson
15 Dec 2016 - Initial version
*/

//#define _DEBUG

void setup()
{
#ifdef _DEBUG
Serial.begin(38400);
Serial.println("wordclok");
#endif

pins.setup();
digitalWrite(PINS::STD_LED, HIGH);
rtc.setup();
#ifndef _DEBUG
randomSeed(rtc.getSeed());
#endif
ldr.setup();
leds.setup();
cfg.setup();
clk.setup();
digitalWrite(PINS::STD_LED, LOW);
}

void loop()
{
clk.loop();
}
32) Arduino Indoor NeoPixel Thermometer
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

NeoPixel
× 1

LCD readout
× 1

TMP36 sensor
× 1

Resistor 1k ohm

× 1
470 ohm resistor
× 1

Rotary potentiometer (generic)

× 1

Simple momentary switch


× 1

F to M jumper wires
× 1
for the LCD
M to M Jumpers
× 1
for everything else
Breadboard (generic)

× 1

ABOUT THIS PROJECT


This is a quick, intermediate Arduino project that takes a temperature
reading from a TMP36 , reads it onto an LCD screen and gives an
"Analog" readout on a Neopixel stick that changes color and number of
lights lit every 10 degrees Fahrenheit. It's easily customizable as
NeoPixels can be coded in many ways so the NeoPixel stick can
change size and colors every which way a maker would want it to.
Step 1: Gather Components
For this build you will need an Arduino (any one will do, I used Uno),
NeoPixels (can be found here) an LCD screen (I used this one) a
TMP36 sensor (or comparable, I used this inexpensive one from
Adafruit ) a 1k ohm resistor, a 470 ohm resistor, a potentiometer, a
simple momentary switch, F to M jumper wires (for the LCD) and M to
M Jumpers (for everything else) and a breadboard.

Step 2: Construct Circuit


Fritzing View of Circuit

From the fritzing diagram the circuit looks a little confusing but it's
actually relatively simple. What is important to take note is you're
going to want the TMP36 on a separate circuit from the rest of the
project because some noise that's caused by the Pixels messes up the
voltage readout from the TMP36 and in turn the temperature reading.
When it comes to the Pixels a bit a soldering is going to have to
happen. You're going to want to use 4 plain, everyday headers, and
solder them directly onto the NeoPixel stick. It's absolutely imperative
that you get the pin out correct on this otherwise you'll have to de and
resolder the headers and trust me, the copper pads on the NeoPixels do
not like being resoldered and while NeoPixels are not the most
expensive component in the world, several sticks that are rendered
unusable because the copper pads have been taken off add up very
quickly. To solder you will want a good iron and a solder with a thin
gauge. A pair of "third hands" are especially useful in this project as the
headers can be tricky to solder onto the stick straight if the stick is
lying on the table.
How I set up the pixels and header in the Third hand
NeoPixel PinOut
I included a photo with the proper pin order, the side with "DIN" goes
to the breadboard/Arduino and the side "DOUT" goes to other pixels or
just the air. You can use any number of NeoPixels, the one at the Studio
has 4 sticks for an especially prominent read out that would be ideal if
you were to enclose it in a laser cut acrylic display (possibly stay
tuned). On the other hand, and as seen in one of the photos, I have a
smaller one using only one stick that works just fine at home that you
could then also turn into a wall mounted display with a very quick
enclosure. That's one of the things with NeoPixels that make them
great, it doesn't take much code to make them fit almost any size or
form factor.
The pin out from the Arduino goes as follows:
A0 to Vout on TMP36
3.3V to TMP36 PWR Rail
AREF to TMP36 PWR Rail //AREF takes a reference voltage and
gives a more accurate reading than just taking //straight from the
source, you'll see why this is important on the next page
GND to TMP36 GND rail
5V to Primary PWR rail
other GND to Primary GND rail
13 to pin 4 on LCD
12 to momentary switch //while not necessary I included a
momentary switch that, when pressed will switch //between Celsius
and Fahrenheit readout on the LCD
11 to pin 6 on LCD
6 to 470 ohm resistor leading to DIN on NeoPixels //resistor
prevents surges and damage to the pixel stick
5 to pin 11 on LCD
4 to pin 12 on LCD
3 to pin 13 on LCD
2 to pin 14 on LCD
Other pinouts on LCD Screen
LCD pin 1 to one leg of potentiometer leading to Primary GND rail
LCD pin 2 to one leg of potentiometer leading to Primary PWR rail
LCD pin 3 to middle leg or "wiper" of potentiometer //this controls
contrast on the screen
LCD pin 5 to primary GND rail
LCD pin 15 to primary PWR rail
LCD pin 16 to primary GND rail
The rest of the circuit is pretty self explanatory and clear on the
Fritzing Diagram, just remember to keep the TMP36 and Primary
circuits separate.
SCHEMATICS
CODE
#include <LiquidCrystal.h>
#include <Adafruit_NeoPixel.h>

// Create a variable that will store the temperature value


int TMPin = 0;
const int button = 12;
int lastColor = -1;

#define aref_voltage 3.3


#define PIN 6

/*
Param 1 == number of pixels
Param 2 == Arduino pin attached to din
Param 3 == pixel type flags, add together as needed
NE0_KHZ800 800 KHZ bitstream (avg neopix)
NE0_GRB wired for GRB bitstream
*/
Adafruit_NeoPixel strip = Adafruit_NeoPixel(32, PIN, NEO_GRB +
NEO_KHZ800); //call Neopixels, 32 pixels in all, on pin 6, RGB system
and 800 KHZ
LiquidCrystal lcd(13, 11, 5, 4, 3, 2); //call LCD display

void setup()
{
lcd.begin(16,2); //initialize LCD screen 16 by 2
strip.begin(); //begin neo pixel strip
strip.show(); //initialize strip
Serial.begin(9600);// serial monitor access
pinMode(button, INPUT); //button for celsius
analogReference(EXTERNAL); //analog reference for use with TMP36
}

void loop()
{
double temperature;
double temp;
double tempF;

temp = tempMeasure(temperature); //call tempMeasure function


tempF = (temp * 9.0/5.0 + 32); //take reading from tempMeasure and
convert to faharenheit

while(digitalRead(button) == false) //button is depressed readout is in


Celsius
{
Serial.println(temp); //prints in serial monitor
lcd.print(temp); //prints on LCD screen
lcd.setCursor(0,1); //sets cursor
delay(2000); //2 seconds between readings
lcd.clear(); //clear LCD after 2 seconds
}

pixelCaseF(tempF); //call pixelCase function that controls lights


Serial.println(tempF); //print in serial
lcd.print(tempF); //print temp in F on LCD
lcd.setCursor(0,1); //set cursor
delay(2000); //take reading every 2 seconds
lcd.clear(); //clear LCD

}//end loop
double tempMeasure(double temperature)
{
// -----------------
// Read temperature
// -----------------

int reading = analogRead(TMPin); //voltage reading


double voltage = reading * aref_voltage; //take initial reading and multiply
by 3.3 ref voltage for arduino

voltage /= 1024.0; //divide reading by 1024 to map

temperature = (voltage - 0.5) * 100; //converts 10mv per degree with 500
mV offset to (voltage - 500mV) * 100)

return temperature; //return temperature to top level method

}//end tempMeasure

void pixelCaseF(double tempF)


/*
This method controls the neo-pixel for the "analog" readout on the
thermometer. With every temperature group, the number of pixels lit
changes along with the color
*/

{
int i;
strip.setBrightness(64);
strip.show();

if (tempF >= 90.05)//if above 90 degrees, strip is red and entire strip is lit
{
strip.clear();
for(int i=0;i <= 32;i++)
{
strip.setPixelColor(i, strip.Color(255,0,0));
}
}
else if (tempF < 90.2 && tempF >= 80.05) //if 90 > tempF >= 80 orange
and strip is partially lit up to 29th pixel
{
strip.clear();
for(int i=0;i <= 28;i++)
{
strip.setPixelColor(i, strip.Color(255,128,0));
}
}
else if (tempF < 80.02 && tempF >= 70.5)// if 80 > tempF >= 70 yellow-
green and strip is lit up to 25th pixel
{
strip.clear();
for(int i = 0; i <= 24; i++)
{
strip.setPixelColor(i,strip.Color(204,255,0));
}
}
else if (tempF < 70 && tempF >= 60.5)// if 70 > tempF >= 60 green and
strip is lit up to 21st pixel
{
strip.clear();
for(int i = 0; i<= 20; i++)
{
strip.setPixelColor(i,strip.Color(0,255,0));
}
}
else if (tempF < 60.02 && tempF >= 50.5) //if 60 > tempF >= 50 blue and
strip is lit up to 17th pixel
{
strip.clear();
for(int i = 0; i <= 16; i++)
{
strip.setPixelColor(i,strip.Color(0,0,255));
}
}
else if (tempF < 50.02 && tempF >= 40.5) //if 50 > tempF >= 40 aqua and
strip is lit to 13th pixel
{
strip.clear();
for(int i = 0; i <= 12; i++)
{
strip.setPixelColor(i, strip.Color(0,255,255));
}
}
else if (tempF < 40.02 && tempF >= 32.5) //if 40 > tempF >= 32 fuschia
and strip is lit to 9th pixel
{
strip.clear();
for(int i = 0; i <= 8; i++)
{
strip.setPixelColor(i, strip.Color(153, 51,255));
}
}
else if (tempF < 32.5) //temp < freezing white and strip is lit to 5th pixel
{
strip.clear();
for(i = 0;i <= 4; i++)
{
strip.setPixelColor(i, strip.Color(255,255,255));
}//end for
}
strip.show(); //update color change

}//end pixelCase

33) Arduino LCD Video Game


COMPONENTS AND SUPPLIES

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Arduino UNO & Genuino UNO


× 1

USB-A to B Cable

× 1

Rotary potentiometer (generic)

× 1

Analog joystick (Generic)


× 1

Buzzer

× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1
APPS AND ONLINE SERVICES

Arduino IDE

ABOUT THIS PROJECT

This is a project that is based on a video game that I found on the


internet. This project has many features such as a buzzer for beeping
when your character collides or jumps over obstacles. Also, to give it a
video game feeling, it has a joystick (must have a button) because you
simply press down on the joystick's button to jump. This video game is
about you guessed it! (A man running and jumping over obstacles and
avoiding them.) The object of this game is about getting as many points
as possible (one point for every second you are on the course and
avoiding the obstacles).
SCHEMATICS
CODE

#include <LiquidCrystal.h>

#define PIN_BUTTON 2
#define PIN_AUTOPLAY 1
#define PIN_BUZZER 8
#define PIN_READWRITE 10
#define PIN_CONTRAST 12

#define SPRITE_RUN1 1
#define SPRITE_RUN2 2
#define SPRITE_JUMP 3
#define SPRITE_JUMP_UPPER '.' // Use the '.' character for the head
#define SPRITE_JUMP_LOWER 4
#define SPRITE_TERRAIN_EMPTY ' ' // User the ' ' character
#define SPRITE_TERRAIN_SOLID 5
#define SPRITE_TERRAIN_SOLID_RIGHT 6
#define SPRITE_TERRAIN_SOLID_LEFT 7

#define HERO_HORIZONTAL_POSITION 1 // Horizontal position of hero on screen

#define TERRAIN_WIDTH 16
#define TERRAIN_EMPTY 0
#define TERRAIN_LOWER_BLOCK 1
#define TERRAIN_UPPER_BLOCK 2
#define HERO_POSITION_OFF 0 // Hero is invisible
#define HERO_POSITION_RUN_LOWER_1 1 // Hero is running on lower row (pose 1)
#define HERO_POSITION_RUN_LOWER_2 2 // (pose 2)

#define HERO_POSITION_JUMP_1 3 // Starting a jump


#define HERO_POSITION_JUMP_2 4 // Half-way up
#define HERO_POSITION_JUMP_3 5 // Jump is on upper row
#define HERO_POSITION_JUMP_4 6 // Jump is on upper row
#define HERO_POSITION_JUMP_5 7 // Jump is on upper row
#define HERO_POSITION_JUMP_6 8 // Jump is on upper row
#define HERO_POSITION_JUMP_7 9 // Half-way down
#define HERO_POSITION_JUMP_8 10 // About to land

#define HERO_POSITION_RUN_UPPER_1 11 // Hero is running on upper row (pose 1)


#define HERO_POSITION_RUN_UPPER_2 12 // (pose 2)

LiquidCrystal lcd(11, 9, 6, 5, 4, 3);


static char terrainUpper[TERRAIN_WIDTH + 1];
static char terrainLower[TERRAIN_WIDTH + 1];
static bool buttonPushed = false;

void initializeGraphics(){
static byte graphics[] = {
// Run position 1
B01100,
B01100,
B00000,
B01110,
B11100,
B01100,
B11010,
B10011,
// Run position 2
B01100,
B01100,
B00000,
B01100,
B01100,
B01100,
B01100,
B01110,
// Jump
B01100,
B01100,
B00000,
B11110,
B01101,
B11111,
B10000,
B00000,
// Jump lower
B11110,
B01101,
B11111,
B10000,
B00000,
B00000,
B00000,
B00000,
// Ground
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
// Ground right
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
// Ground left
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
};
int i;
// Skip using character 0, this allows lcd.print() to be used to
// quickly draw multiple characters
for (i = 0; i < 7; ++i) {
lcd.createChar(i + 1, &graphics[i * 8]);
}
for (i = 0; i < TERRAIN_WIDTH; ++i) {
terrainUpper[i] = SPRITE_TERRAIN_EMPTY;
terrainLower[i] = SPRITE_TERRAIN_EMPTY;
}
}

// Slide the terrain to the left in half-character increments


//
void advanceTerrain(char* terrain, byte newTerrain){
for (int i = 0; i < TERRAIN_WIDTH; ++i) {
char current = terrain[i];
char next = (i == TERRAIN_WIDTH-1) ? newTerrain : terrain[i+1];
switch (current){
case SPRITE_TERRAIN_EMPTY:
terrain[i] = (next == SPRITE_TERRAIN_SOLID) ? SPRITE_TERRAIN_SOLID_RIGHT :
SPRITE_TERRAIN_EMPTY;
break;
case SPRITE_TERRAIN_SOLID:
terrain[i] = (next == SPRITE_TERRAIN_EMPTY) ? SPRITE_TERRAIN_SOLID_LEFT :
SPRITE_TERRAIN_SOLID;
break;
case SPRITE_TERRAIN_SOLID_RIGHT:
terrain[i] = SPRITE_TERRAIN_SOLID;
break;
case SPRITE_TERRAIN_SOLID_LEFT:
terrain[i] = SPRITE_TERRAIN_EMPTY;
break;
}
}
}

bool drawHero(byte position, char* terrainUpper, char* terrainLower, unsigned int score) {
bool collide = false;
char upperSave = terrainUpper[HERO_HORIZONTAL_POSITION];
char lowerSave = terrainLower[HERO_HORIZONTAL_POSITION];
byte upper, lower;
switch (position) {
case HERO_POSITION_OFF:
upper = lower = SPRITE_TERRAIN_EMPTY;
break;
case HERO_POSITION_RUN_LOWER_1:
upper = SPRITE_TERRAIN_EMPTY;
lower = SPRITE_RUN1;
break;
case HERO_POSITION_RUN_LOWER_2:
upper = SPRITE_TERRAIN_EMPTY;
lower = SPRITE_RUN2;
break;
case HERO_POSITION_JUMP_1:
case HERO_POSITION_JUMP_8:
upper = SPRITE_TERRAIN_EMPTY;
lower = SPRITE_JUMP;
break;
case HERO_POSITION_JUMP_2:
case HERO_POSITION_JUMP_7:
upper = SPRITE_JUMP_UPPER;
lower = SPRITE_JUMP_LOWER;
break;
case HERO_POSITION_JUMP_3:
case HERO_POSITION_JUMP_4:
case HERO_POSITION_JUMP_5:
case HERO_POSITION_JUMP_6:
upper = SPRITE_JUMP;
lower = SPRITE_TERRAIN_EMPTY;
break;
case HERO_POSITION_RUN_UPPER_1:
upper = SPRITE_RUN1;
lower = SPRITE_TERRAIN_EMPTY;
break;
case HERO_POSITION_RUN_UPPER_2:
upper = SPRITE_RUN2;
lower = SPRITE_TERRAIN_EMPTY;
break;
}
if (upper != ' ') {
terrainUpper[HERO_HORIZONTAL_POSITION] = upper;
collide = (upperSave == SPRITE_TERRAIN_EMPTY) ? false : true;
}
if (lower != ' ') {
terrainLower[HERO_HORIZONTAL_POSITION] = lower;
collide |= (lowerSave == SPRITE_TERRAIN_EMPTY) ? false : true;
}

byte digits = (score > 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 <= HERO_POSITION_RUN_LOWER_2) heroPos =
HERO_POSITION_JUMP_1;
buttonPushed = false;
digitalWrite(PIN_BUZZER,HIGH);
}

if (drawHero(heroPos, terrainUpper, terrainLower, distance >> 3)) {


playing = false; // The hero collided with something. Too bad.
for (int i = 0; i <= 2; i++) {
digitalWrite(PIN_BUZZER, HIGH);
delay(100);
digitalWrite(PIN_BUZZER, LOW);
delay(100);
}
} else {
if (heroPos == HERO_POSITION_RUN_LOWER_2 || heroPos ==
HERO_POSITION_JUMP_8) {
heroPos = HERO_POSITION_RUN_LOWER_1;
} else if ((heroPos >= HERO_POSITION_JUMP_3 && heroPos <=
HERO_POSITION_JUMP_5) && terrainLower[HERO_HORIZONTAL_POSITION] !=
SPRITE_TERRAIN_EMPTY) {
heroPos = HERO_POSITION_RUN_UPPER_1;
} else if (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
× 1

Texas Instruments Dual H-Bridge


motor drivers L293D
× 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 H-
bridge 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

Jumper wires (generic)

× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1

USB-A to B Cable

× 1

Arduino UNO & Genuino UNO

× 1

Rotary potentiometer (generic)

× 1

SparkFun Pushbutton switch 12mm

× 1

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 <LiquidCrystal.h>
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

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Adafruit MAX98357A
× 1

Speaker: 3W, 4 ohms

× 1

RobotGeek Slider

× 2
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 <I2S.h>

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 HC-
05

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

HC-05 Bluetooth Module


× 1

Jumper wires (generic)

× 1

Two AC Bulbs(Red,Yellow)
× 1

Relay (generic)
× 1
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

× 1

Ultrasonic Sensor - HC-SR04


(Generic)
× 1

Relay Module (Generic)


This will be used just to make
some noise when the relay
× 1
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

ultrasonic sensor HR SC-04


× 1
LED (generic)

× 2

Buzzer

× 1

Resistor 10k ohm

× 2

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 <= 50 && 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 <= 20)
{
digitalWrite(2, HIGH);
tone(buzz, 2000);
delay(100);
noTone(buzz);
delay(100);
tone(buzz, 2000);
delay(100);
noTone(buzz);
delay(100);
tone(buzz, 2000);
delay(100);
noTone(buzz);
tone(buzz, 2000);
delay(100);
noTone(buzz);
delay(100);
}
else
{
digitalWrite(2, LOW); // turn the LED off by making the voltage LOW
// wait for a second
}
}
Step 4: Flash the Arduino board
After making all the connections, we are ready to upload the program to
the Arduino board. Please see the attached image for reference.
Step 5: How this system works
Let me explain for you how this system works. I defined three different
zones:
Zone 1: No warning
Zone 2: Only visual warning (in this zone, driver has to pay attention)
Zone 3: Both visual and audio warning (driver has to take necessary
action to avoid collision)
SCHEMATICS

Please use this pin information. You can change pin number as per
yours but in that case you have to change code also.
Arduino based collision detection warning system
Please follow this schematic to connect hardware to board and pin
numbers.
CODE

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 <= 50 && 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 <= 20)


{
digitalWrite(2, HIGH);

tone(buzz, 2000);
delay(100);
noTone(buzz);
delay(100);

tone(buzz, 2000);
delay(100);
noTone(buzz);
delay(100);

tone(buzz, 2000);
delay(100);
noTone(buzz);

tone(buzz, 2000);
delay(100);
noTone(buzz);
delay(100);
}

else
{
digitalWrite(2, LOW); // turn the LED off by making the voltage LOW
// wait for a second
}
}

40) Arduino GPS Data Logger Real Time Curve Max Height and Max
Speed
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO


arduino uno
× 1

Jumper (Busbar), Jumper Leads Set


× 1

Arduino Proto Shield

× 1

1.8" TFT SPI LCD Screen with


MicroSD Socket × 1
or another with SD card
u-blox gps neo 6m
× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Solder Wire, Lead Free

Wire Stripper & Cutter, 18-10 AWG / 0.75-


4mm² Capacity Wires

ABOUT THIS PROJECT

I practice aeromodelling and I like to know the speed and altitude of


my planes. unfortunately, commercial GPS data loggers are very
expensive.
So I decided to make a GPS data logger based on Arduino for a cost
less than 50€.
My first prototype is based on Arduino Uno R3 with a Sainsmart
ST7735 screen with integrated SD card and a NEO 6M V2 GPS
module.
In the second project I would use an Arduino Nano with an SSD1306
OLED screen, the same GPS module, and a micro SD card. The weight
with case should be around 40 grams and can easily be integrated into a
medium-sized aircraft (size L 50 mm X l 30mm X H 22mm).
SCHEMATICS

CODE

gps data logger Arduino


#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define cs 10
#define dc 9
#define rst 8
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
static const int RXPin = 4, TXPin = 3; //GPS communication
static const uint32_t GPSBaud = 9600;

#define OLED_RESET 5

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

int x=80;
int xh=80;
int maxhigh=0;
int maxspeed = 0, speed1 = 0;
int high1 = 0;;

void setup()
{

Serial.begin(9600);
ss.begin(GPSBaud);

tft.initR(INITR_GREENTAB);
tft.fillScreen(ST7735_BLACK);
tft.setCursor(5, 58);
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("initilisation");

void loop()
{

tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);

// affichage des informations a chaque bonne reception satellite


while (ss.available() > 0){
gps.encode(ss.read());
if (gps.location.isUpdated()){
cadre();

tft.setCursor(5, 44);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("Latitude :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.location.lat(), 6);
tft.setCursor(5, 58);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("Longitude :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.location.lng(), 6);

//affichage ecran date


tft.setCursor(5, 7);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("date : ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.date.day());
tft.print(" ");
tft.print(gps.date.month());
tft.print(" ");
tft.print(gps.date.year());

//affichage ecran heure


tft.setCursor(5, 20);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("heure : ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.time.hour()+1);
tft.print(" ");
tft.print(gps.time.minute());
tft.print(" ");
tft.print(gps.time.second());
tft.print(" ");
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.setCursor(3, 30);

//affichage ecran altitude


tft.setCursor(5, 80);
tft.print("H m :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print (gps.altitude.meters(),0);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.setCursor(5, 95);
hmax();
tft.print("Hmax :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(maxhigh);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
courbeh();

//affichage ecran vitesse


tft.setCursor(5, 115);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("V act: ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print (gps.speed.kmph(),0);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
tft.setCursor(5, 130);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
vmax();
tft.print("vmax: ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(maxspeed);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
courbe();
//affichage ecran nombre de satellites
tft.setCursor(5, 147);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("nombre de Sat : ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.satellites.value());
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");

// Horizontal Dim. of Precision (100ths-i32)


Serial.print("HDOP = ");
Serial.println(gps.hdop.value());

smartDelay(400);

}
}
}
// delai pour une bonne recption
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
void cadre() {
// affichage ecran
//cadre
tft.drawLine(0,0,130,0,ST7735_RED);
tft.drawLine(0,1,130,1,ST7735_RED);
tft.drawLine(0,158,130,158,ST7735_RED);
tft.drawLine(0,142,130,142,ST7735_RED);
tft.drawLine(0,141,130,141,ST7735_RED);
tft.drawLine(0,107,130,107,ST7735_RED);
tft.drawLine(0,108,130,108,ST7735_RED);

tft.drawLine(80,108,80,140,ST7735_RED);
tft.drawLine(81,109,81,140,ST7735_RED);

tft.drawLine(80,70,80,108,ST7735_RED);
tft.drawLine(81,70,81,108,ST7735_RED);

tft.drawLine(0,159,130,159,ST7735_RED);
tft.drawLine(0,0,0,156,ST7735_RED);
tft.drawLine(1,1,1,157,ST7735_RED);
tft.drawLine(127,0,127,156,ST7735_RED);
tft.drawLine(126,0,126,156,ST7735_RED);
tft.drawLine(0,35,130,35,ST7735_RED);
tft.drawLine(0,36,130,36,ST7735_RED);
tft.drawLine(0,70,130,70,ST7735_RED);
tft.drawLine(0,71,130,71,ST7735_RED);

void courbe() {

int nouvelleValeur;

// converison vitesse max (350 km/h) en pixel


nouvelleValeur = map((gps.speed.kmph()), 0, 150, 137, 110); // car l'cran a 64 pixels de
haut

x++;

tft.drawPixel(x,nouvelleValeur,ST7735_CYAN);
if (x>123) {
x=80;
tft.fillRect(82,110,43,30,ST7735_BLACK);

}
}
void courbeh() {

int nouvelleValeurh;
// converison vitesse max (350 km/h) en pixel
nouvelleValeurh = map((gps.altitude.meters()), 0, 1000, 104, 72); // car l'cran a 64 pixels de
haut

xh++;

tft.drawPixel(xh,nouvelleValeurh,ST7735_CYAN);
if (xh>123) {
xh=80;
tft.fillRect(82,72,43,35,ST7735_BLACK);

}
}
void vmax() {
// calcul vitese maximum
speed1 = (gps.speed.kmph());
if ( speed1 > maxspeed) {
maxspeed = speed1;
}
}
void hmax() {
// calcul altitude maximum
high1 = (gps.altitude.meters());
if ( high1 > maxhigh) {
maxhigh = high1;
}
}

sauvegarde SD
#include <SPI.h>
#include<SD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#define cs 10
#define dc 9
#define rst 8
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
static const int RXPin = 4, TXPin = 3; //GPS communication
static const uint32_t GPSBaud = 9600;
const int cs_sd=4;
#define OLED_RESET 5

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

int x=80;
int xh=80;
int maxhigh=0;
int maxspeed = 0, speed1 = 0;
int high1 = 0;;

void setup()
{

Serial.begin(9600);
ss.begin(GPSBaud);
tft.initR(INITR_GREENTAB);
tft.fillScreen(ST7735_BLACK);
tft.setCursor(5, 58);
tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("initilisation");
tft.setCursor(5, 70);
tft.print("init SD");
delay(1000);
if(!SD.begin(cs_sd)) //Condition vrifiant si la carte SD est prsente dans l'appareil
{
tft.setCursor(5, 82);
tft.print("Defaut SD");
return;
}
tft.setCursor(5, 82);
tft.print("Carte SD OK");

delay(1000);
tft.fillScreen(ST7735_BLACK);

File data = SD.open("donnees.txt",FILE_WRITE); // Ouvre le fichier "donnees.txt"


data.println(""); data.println("Dmarrage acquisition"); // Ecrit dans ce fichier
data.close();
}

void loop()
{

tft.setTextSize(1);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);

// affichage des informations a chaque bonne reception satellite


while (ss.available() > 0){
gps.encode(ss.read());
if (gps.location.isUpdated()){

cadre();

tft.setCursor(5, 44);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("Latitude :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.location.lat(), 6);
tft.setCursor(5, 58);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("Longitude :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.location.lng(), 6);

//affichage ecran date


tft.setCursor(5, 7);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("date : ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.date.day());
tft.print(" ");
tft.print(gps.date.month());
tft.print(" ");
tft.print(gps.date.year());

String Date=String(gps.date.day())+(" ")+(gps.date.month())+(" ")+(gps.date.year());

//affichage ecran heure


tft.setCursor(5, 20);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("heure : ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.time.hour()+1);
tft.print(" ");
tft.print(gps.time.minute());
tft.print(" ");
tft.print(gps.time.second());
tft.print(" ");
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.setCursor(3, 30);

String Temps=String(gps.time.hour()+1)+(" ")+(gps.time.minute())+(" ")+


(gps.time.second());

//affichage ecran altitude


tft.setCursor(5, 80);
tft.print("H m :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print (gps.altitude.meters(),0);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.setCursor(5, 95);
hmax();
tft.print("Hmax :");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(maxhigh);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
courbeh();

//affichage ecran vitesse


tft.setCursor(5, 115);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("V act: ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print (gps.speed.kmph(),0);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
tft.setCursor(5, 130);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
vmax();
tft.print("vmax: ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(maxspeed);
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
courbe();

//affichage ecran nombre de satellites


tft.setCursor(5, 147);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.print("nombre de Sat : ");
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(gps.satellites.value());
tft.setTextColor(ST7735_CYAN,ST7735_BLACK);
tft.print(" ");

// Horizontal Dim. of Precision (100ths-i32)


Serial.print("HDOP = ");
Serial.println(gps.hdop.value());

smartDelay(400);

// Ecriture des donnes dans le fichier texte


File data=SD.open("donnees.txt",FILE_WRITE);
data.println(Date + " " + Temps + " " + String(gps.location.lat(), 6)+"
"+String(gps.location.lng(), 6)+(" ")+String(gps.altitude.meters(),0)+("
")+String(maxhigh)+(" ")+String(gps.speed.kmph(),0)+(" ")+String(maxspeed));
data.close();
}
}
}
// delai pour une bonne recption
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
void cadre() {
// affichage ecran
//cadre
tft.drawLine(0,0,130,0,ST7735_RED);
tft.drawLine(0,1,130,1,ST7735_RED);
tft.drawLine(0,158,130,158,ST7735_RED);
tft.drawLine(0,142,130,142,ST7735_RED);
tft.drawLine(0,141,130,141,ST7735_RED);
tft.drawLine(0,107,130,107,ST7735_RED);
tft.drawLine(0,108,130,108,ST7735_RED);

tft.drawLine(80,108,80,140,ST7735_RED);
tft.drawLine(81,109,81,140,ST7735_RED);

tft.drawLine(80,70,80,108,ST7735_RED);
tft.drawLine(81,70,81,108,ST7735_RED);

tft.drawLine(0,159,130,159,ST7735_RED);
tft.drawLine(0,0,0,156,ST7735_RED);
tft.drawLine(1,1,1,157,ST7735_RED);
tft.drawLine(127,0,127,156,ST7735_RED);
tft.drawLine(126,0,126,156,ST7735_RED);
tft.drawLine(0,35,130,35,ST7735_RED);
tft.drawLine(0,36,130,36,ST7735_RED);
tft.drawLine(0,70,130,70,ST7735_RED);
tft.drawLine(0,71,130,71,ST7735_RED);

void courbe() {

int nouvelleValeur;
// converison vitesse max (350 km/h) en pixel
nouvelleValeur = map((gps.speed.kmph()), 0, 150, 137, 110); // car l'cran a 64 pixels de
haut

x++;

tft.drawPixel(x,nouvelleValeur,ST7735_CYAN);
if (x>123) {
x=80;
tft.fillRect(82,110,43,30,ST7735_BLACK);

}
}
void courbeh() {

int nouvelleValeurh;

// converison vitesse max (350 km/h) en pixel


nouvelleValeurh = map((gps.altitude.meters()), 0, 1000, 104, 72); // car l'cran a 64 pixels de
haut

xh++;

tft.drawPixel(xh,nouvelleValeurh,ST7735_CYAN);
if (xh>123) {
xh=80;
tft.fillRect(82,72,43,35,ST7735_BLACK);

}
}
void vmax() {
// calcul vitese maximum
speed1 = (gps.speed.kmph());
if ( speed1 > maxspeed) {
maxspeed = speed1;
}
}
void hmax() {
// calcul altitude maximum
high1 = (gps.altitude.meters());
if ( high1 > maxhigh) {
maxhigh = high1;
}
}

41) Arduino Doorbell


COMPONENTS AND SUPPLIES
Arduino MKR1000

× 2
NECESSARY TOOLS AND MACHINES
3D Printer (generic)
APPS AND ONLINE SERVICES
Arduino IoT Cloud

Arduino Web Editor

ABOUT THIS PROJECT

The Doorbell is a great example of how to connect your devices to


Arduino Cloud and make them talk to each other.
The Doorbell allows you to open the door from everywhere as long as a
WiFi network is available.
The project is composed of two part: the transmitter and the receiver. The
transmitter is the one that actually opens the door and it is connected to it.
The receiver is the device that rings and that you can use to open the door
from everywhere.
Understanding Arduino Cloud

Arduino Cloud is a simple tool to connect your Arduino/Genuino boards


to the internet and to each other through an mqtt communication.
Mqtt is a machine-to-machine connectivity protocol that allows publishers
and subscribers to exchange messages.
The connection between two different devices happens when one device
subscribes to the topic in which the other one is publishing information.
Getting Started with Arduino Cloud
If this is the first time you are using Arduino Cloud we highly encourage
to follow the getting started guide.

Following a few simple configurations steps you will be given a basic


Arduino sketch to start your project.
In the example's code is important to understand how to publish and how
to receive messages.
In order to publish a message we will use:
client.publish("/username/device1/topic", "text");
While the username and the device name were defined before, the topic
can be named as we like, it is where our messages will be published.
The text field is the message we want to publish in a string format.
In order to receive a message we first have to subscribe to a topic, where
some other device is publishing:
client.subscribe("/username2/device2/ChannelName2");
Those fields have to be filled with the credential of the transmitter device.
Now we receive messages and read them using this code:
void messageReceived(String topic, String payload, char * bytes, unsigned
int length) {
Serial.println(payload)
}
The Receiver
Now we can start building up our project.
We want the receiver to play a song when the right message is received
and to send the "open" message when the button is pressed.
To do so we need to connect to our board a button, a speaker and an sd
breakout board.

In order to make it play we need the AudioZero library. For better quality
the Audio file to store on the SD card must be in the .wav format with
88200 Hz, 8-bit unsigned PCM mono quality. This type of file can be
easily obtained using audio programs like audacity.
The Transmitter
Please note that for this example we presume our door is already
connected to a relay that can lock and unlock the door by switching on and
off.
What remains to do is simply to connect our board to this relay and to the
front door button.
SCHEMATICS

Receiver

Transmitter
CODE

Doorbell Receiver

#include <SPI.h>
#include <WiFi101.h>
#include <WiFiSSLClient.h>
#include <MQTT.h>
#include <SD.h>
#include <AudioZero.h>

///////please enter your sensitive data in the Secret tab/arduino_secrets.h


/////// Wifi Settings ///////
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;

// Arduino Cloud settings and credentials


const char userName[] = SECRET_USER_NAME;
const char deviceName[] = SECRET_DEVICE_NAME;
const char deviceId[] = SECRET_DEVICE_ID;
const char devicePsw[] = SECRET_DEVICE_PSW;

int status = WL_IDLE_STATUS;


volatile bool buttonPressed = false;

MQTTClient client;
WiFiSSLClient net;

void setup() {
Serial.begin(9600);
WiFi.begin(ssid, pass);
client.begin("mqtt-dev.arduino.cc", 8883, net);
connect();
client.subscribe("/tommasltrz/DoorbellTransmitter/bell");
// setup SD-card
Serial.print("Initializing SD card...");
if (!SD.begin(6)) {
Serial.println(" failed!");
while (true);
}
Serial.println(" done.");

pinMode(4, INPUT);
attachInterrupt(4, buttonPressedCallback, RISING);
}

void connect() {
Serial.print("checking wifi...");
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, p);
delay(4000);
}

Serial.println("connecting...");
while (!client.connect(deviceName, deviceId, devicePsw)) {
Serial.print(".");
}
Serial.println("connected!");
}

void loop() {
client.loop();

if (buttonPressed) {
client.publish("/tommasltrz/DoorbellReciever/bell", "open");
Serial.println("publishing up");
buttonPressed = false;
delay(1000);
}
}

void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
if (payload.equals("ring")) {
AudioZero.begin(2 * 44100); // 44100kHz stereo => 88200 sample rate
File myFile = SD.open("test.wav"); // open wave file from sdcard
if (!myFile) {
Serial.println("error opening test.wav");
while (true);
}
Serial.print("Playing");
AudioZero.play(myFile);
Serial.println("End");
AudioZero.end();
}
}

void buttonPressedCallback() {
buttonPressed = true;
}

Doorbel Transmitter

#include <SPI.h>
#include <WiFi101.h>
#include <WiFiSSLClient.h>
#include <MQTTClient.h>

///////please enter your sensitive data in the Secret tab/arduino_secrets.h


/////// Wifi Settings ///////
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;

// Arduino Cloud settings and credentials


const char userName[] = SECRET_USER_NAME;
const char deviceName[] = SECRET_DEVICE_NAME;
const char deviceId[] = SECRET_DEVICE_ID;
const char devicePsw[] = SECRET_DEVICE_PSW;

int status = WL_IDLE_STATUS;


volatile bool buttonPressed = false;

MQTTClient client;
WiFiSSLClient net;

void setup() {
Serial.begin(9600);
WiFi.begin(ssid, password);
client.begin("mqtt-dev.arduino.cc", 8883, net);
connect();
client.subscribe("/tommasltrz/DoorbellReciever/bell");

pinMode(4, INPUT);
pinMode (6, OUTPUT);
attachInterrupt(4, buttonPressedCallback, RISING);
digitalWrite(6, LOW);

}
void connect() {
Serial.print("checking wifi...");
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, password);
delay(4000);
}

Serial.println("connecting...");
while (!client.connect(deviceName, deviceId, devicePsw)) {
Serial.print(".");
}
Serial.println("connected!");
}
void loop() {
client.loop();

if (buttonPressed) {
client.publish("/tommasltrz/DoorbellTransmitter/bell", "ring");
Serial.println("publishing up");
buttonPressed = false;
delay(1000);
}

}
void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
if (payload.equals("open")) {
digitalWrite(6, HIGH);
delay(1000);
digitalWrite(6, LOW);
buttonPressed = false;
}
}
void buttonPressedCallback() {
buttonPressed = true;
}

42) PinBall Table on Arduino


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

RobotGeek 180 Degree Robot


Servo
× 1

LED (generic)
× 1

Breadboard (generic)

× 1

ABOUT THIS PROJECT

Step 1
The first thing I made was the wooden housing. Then I decorate the body.
I glued the body of the game table.
Step 2
After that, it was necessary to strengthen the housing wall qualitatively. I
used glue, nails and screws.
This action can be done either now or later, but I did it at first. I glued
down the right side. I measured the height - it was 13 cm, and the lowest
part body - 11 cm. The higher the slope, the more difficult you will run the
iron (or another material ball). The body length received 50 cm.
Invisible player hardware component.
Designing and painting most of the board.
Step 3
Production of some of the details on the 3D printer.
Opening holes on the upper platform. I have made but not yet connected
the first actuator.
The Circuit
Wiring
The sensors
SCHEMATICS
CODE

main game

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C myDisplay(0x27,16,2);

#define greenLED 2
#define yellowLED 3
#define redLED 4
#define sensor1 8
#define sensor2 9
#define sensor3 10
#define sensor4 11
#define sensor5 12
#define sensor6 13

void setup()
{
myDisplay.init();
myDisplay.backlight();
myDisplay.print("PLAY!");
delay(2000);
myDisplay.setCursor(0,0);
myDisplay.print(" ");
myDisplay.setCursor(6,0);
myDisplay.print("GO GO GO");
delay(2000);
myDisplay.setCursor(0,0);
myDisplay.print(" ");

Serial.begin(9600);
pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);
pinMode(sensor3, INPUT);
pinMode(sensor4, INPUT);
pinMode(sensor5, INPUT);
pinMode(sensor6, INPUT);
pinMode(greenLED, OUTPUT);
pinMode(yellowLED, OUTPUT);
pinMode(redLED, OUTPUT);

digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);
digitalWrite(redLED, LOW);

int i=0;
void loop() {
if (digitalRead(sensor1)==HIGH){
i=i+20;
myDisplay.clear();
myDisplay.setCursor(5,0);
myDisplay.print("+20!");
digitalWrite(greenLED, HIGH);
delay(2000);
digitalWrite(greenLED, LOW);
myDisplay.clear();
}

if (digitalRead(sensor2)==HIGH){
i=i+50;
myDisplay.clear();
myDisplay.setCursor(5,0);
myDisplay.print("+50!");
digitalWrite(greenLED, HIGH);
digitalWrite(yellowLED, HIGH);
delay(2000);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);
myDisplay.clear();
}

if (digitalRead(sensor3)==HIGH){
i=i+100;
myDisplay.clear();
myDisplay.setCursor(5,0);
myDisplay.print("+100!");
digitalWrite(greenLED, HIGH);
digitalWrite(yellowLED, HIGH);
digitalWrite(redLED, HIGH);
delay(2000);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);
digitalWrite(redLED, LOW);
myDisplay.clear();
}

if (digitalRead(sensor4)==HIGH){
i=i+20;
myDisplay.clear();
myDisplay.setCursor(5,0);
myDisplay.print("+20!");
digitalWrite(greenLED, HIGH);
delay(2000);
digitalWrite(greenLED, LOW);
myDisplay.clear();
}

if (digitalRead(sensor5)==HIGH){
i=i+50;
myDisplay.clear();
myDisplay.setCursor(5,0);
myDisplay.print("+50!");
digitalWrite(greenLED, HIGH);
digitalWrite(yellowLED, HIGH);
delay(2000);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);
myDisplay.clear();
}
if (digitalRead(sensor6)==HIGH){
i=i+100;
myDisplay.clear();
myDisplay.setCursor(5,0);
myDisplay.print("+100!");
digitalWrite(greenLED, HIGH);
digitalWrite(yellowLED, HIGH);
digitalWrite(redLED, HIGH);
delay(2000);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);
digitalWrite(redLED, LOW);
myDisplay.clear();
}

if (i>=500){
myDisplay.clear();
myDisplay.setCursor(4,0);
myDisplay.print("YOU WIN!");
for (int j=0; j<=15; j=j+1){
digitalWrite(greenLED, HIGH);
digitalWrite(yellowLED, HIGH);
digitalWrite(redLED, HIGH);
delay(100);
digitalWrite(greenLED, LOW);
digitalWrite(yellowLED, LOW);
digitalWrite(redLED, LOW);
delay(100);
}
i=0;
myDisplay.clear();
myDisplay.setCursor(0,0);
myDisplay.print("New Game");
delay(2000);
myDisplay.setCursor(0,0);
myDisplay.print(" ");
myDisplay.setCursor(6,0);
myDisplay.print("GO!");
delay(2000);
myDisplay.setCursor(0,0);
myDisplay.print(" ");
}

myDisplay.setCursor(0,0);
myDisplay.print("Your Score:");
myDisplay.setCursor(0,1);
myDisplay.print(i,DEC);
}

for servo

#include <Servo.h>

#define servopin 5
Servo myservo;

void setup()
{
myservo.attach(servopin);
myservo.write(90);

void loop() {
myservo.write(160);
delay(1000);
myservo.write(30);
delay(1000);
}

43) Arduino RFID Dropbox Logger


COMPONENTS AND SUPPLIES

Arduino Yun

× 1

Jumper wires (generic)


× 1

Breadboard (generic)

× 1

RFID Reader Module


× 1
APPS AND ONLINE SERVICES
Arduino Web Editor

Adafruit IO

IFTTT Maker service

ABOUT THIS PROJECT

Have you ever wanted a system that keeps track of the time at which your
employees arrive to work, have you ever wanted to check the time at
which a person enters your room (I have), this device aims to make all of
that as simple as possible. RFIDDropboxLogger will keep track of
everyone scanning an RFID card using an RFID module and will write to
Dropbox whenever it happens to keep you updated with all the
information. Thanks to IFTTT, this is all possible and easy to do.
A Single Component
RFID Module
Result
Functionality
This project will require IFTTT to work, to connect to IFTTT we will have
to use another cloud-based platform called Adafruit IO. This platform will
allow us to easily connect our Arduino Yún to the Cloud and then to
IFTTT. Here is an image illustrating the process.
The Arduino Yún will monitor the RFID module searching for a card,
when one is detected, the micro controller will increment the value to send
by 1 and then parse the value to Adafruit IO. Using an IFTTT trigger,
whenever a change in value is detected on Adafruit IO, (in our case, the
variable incrementation) the app will trigger a Dropbox trigger which will
append the time at which an RFID card had been scanned to a text file.
Note that this operation will last approximately 15 minutes. Here is an
image illustrating the code.

Code Overview
If(RFID Card Present) will check if an RFID card is present.
Increase value will increment the value to send by 1.
Send value will send the incremented value to Adafruit IO.
An Adafruit IO and IFTTT accounts are required to create the project, a
guide to creating these is in Constructing the Project below.
Benefits
The user operating this project will benefit in:
Monitoring RFID usage
Monitoring time of RFID usage
Monitoring amount of times the RFID module has been used
Constructing the Project
Step 1: Required Apparatus
The project requires very few things.
Jumper Wires (Male to Male & Male to Female)
1 Arduino Yún
1 RFID Module (RC522)
1 Breadboard

All the Components


Step 2: Connecting the Circuit
A simple circuit, just connect the RFID module to the Arduino Yún. Here
is an image displaying the project's schematics.

The Schematics
Step 3: Acknowledging the Code
There are three main parts to the code:
connect to MQTT
search for RFID
send value
Each part will be explained below.
Connect to MQTT
void MQTTConnect()
{
int8_t ret;
if(mqtt.connected()) // if already connected
{
return;
}
if(proDebug == 1)
{
Serial.println("Connecting to Server");
}
while((ret = mqtt.connect()) != 0) // attempt to connect
{
if(proDebug == 1)
{
Serial.print(" Error - ");
Serial.println(mqtt.connectErrorString(ret));
Serial.println(" Attempting Reconnection in 5 seconds");
}
mqtt.disconnect();
delay(5000);
}
if(proDebug == 1)
{
Serial.println(" Success - Connection Established");
Serial.println("Scan Card");
Serial.println("");
}
}
This part of the code will connect the Arduino to MQTT services on
Adafruit IO, this will allow the Arduino Yún to write to a Feed on
Adafruit IO.
Search for RFID
if(!mfrc522.PICC_IsNewCardPresent())
{
return;
}
if(!mfrc522.PICC_ReadCardSerial())
{
return;
}
String content = ""; // string to store card id
// store card id
for(byte i = 0; i < mfrc522.uid.size; i++)
{
// store the card id number in a variable
content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
content.concat(String(mfrc522.uid.uidByte[i], HEX));
}
This part will search for a new RFID card and continue with the code once
one is found, the card's ID is also collected and stored to a variable though
not essential.
Send Value
valueToSend++; // increase value to trigger write
if(proDebug == 1)
{
Serial.print("Publishing ");
Serial.println(valueToSend);
}
Console.println(valueToSend);
if(!sendToDropbox.publish(valueToSend))
{
if(proDebug == 1)
{
Serial.println(F(" Error - Failed to Send Data"));
}
}
else
{
if(proDebug == 1)
{
Serial.println(F(" Success - Data Sent"));
}
}
This part will increase the send value variable by 1 so that IFTTT can
detect a change. Then the value will be sent to Adafruit IO, after the
variable is parsed, the Arduino will verify that it has been sent.
This loop will repeat continuously allowing cards to be constantly
scanned, it may take about 15 minutes for IFTTT to check if the value on
the Adafruit IO feed has changed.
Setting up the Variables
Ensure that all variables marked TODO are edited to preference. Insert
your Adafruit IO credentials in the appropriate sections (configuration
illustrated below) and set proDebug to 1 or 0. Note that mode 1 will
enable debugging and will require connection to a Mac/PC and the Serial
Monitor open to work. Default set to 1.
Libraries
Bridge & Bridge Client - copyright (c) Arduino LLC under the GNU
Lesser General Public Licence, this library is in the public domain.
Console - copyright (c) 2013 Arduino LLC under the GNU Lesser
General Public Licence, this library is in the public domain.
SPI - copyright (c) 2015 Hristo Gochkov under the GNU Lesser
General Public Licence, this library is in the public domain.
MFRC522 - this library is in the public domain.
Adafruit MQTT & Adafruit MQTT Client - copyright (c) 2015 Adafruit
Industries under the MIT Licence.
Adafruit IO Setup
Step 1: Download libraries
The first thing to do is to open the Arduino Library manager and search
for Adafruit_MQTT_Library, and then download it.
Step 2: Create an Adafruit IO account
Follow the images below illustrating this process.
Step 3: Configure Adafruit IO
Follow these images to configure feeds for the Adafruit IO communication
with IFTTT.
Click on the feeds button in the menu on the left side of the page

Click on Actions in the fallowing window


Click on Create a New Feed form the dropdown menu

Call this feed "sendToDropbox"

Repeat the steps to create another feed called "subscribeA" and you
are done
IFTTT Setup
Nearly there, now we have to configure IFTTT to finish the project off.
Use the following steps to configure IFTTT; if you already have an IFTTT
account, you may skip the first step.
Step 1: Create an IFTTT Account
You can download the IFTTT app for Apple or Android if you want, the
setup in this tutorial will be done on the app, but it can also be done on
the IFTTT Website. Follow the images below to set up your account.

Open ifttt.com, Click the Sign Up button at the top right corner of the page
Choose to Sign Up with Google or Facebook and fallow the steps
provided
Step 2: Create a Trigger
We will use the app for this step as it is slightly easier, follow the images
for the setup.
Open the IFTTT app, Click on My Applets at the bottom of the screen
Click on the + button at the top right corner of the page
select the + button on the page that opens

On the fallowing page, search for "Adafruit" in the search bar and
click on the trigger below, you will be instructed to connect to Adafruit,
fallow the steps

Chose "Any New Data" on the fallowing window

Click on the Feed Name Box and choose sendToDropbox, click next
when you are done.

Now click the other + button on the opening page


Search for "Dropbox" in the search bar, you will be instructed to link
your Dropbox account, fallow the steps given

Now click on Append to a text file

Set the name, content and folder path of the file, for best experience,
keep content the same as in image, click next

Now enable Notifications if you want and you will receive a


notification every time the Applet triggers, click Finish

Setup
Follow the images below to get the credentials required for the project.

Open io.adafruit.com, select Dashboards from the left side menu


Click on a dashboard or create one by selecting Actions | New Dashboard

Now click on the Key icon at the top right of the page
Copy the Active key and paste it in the required location in the
Arduino Sketch
Obtaining your username is easy, just copy your username and paste it in
the required location int the Arduino Sketch. Now connect your Arduino
Yún to your Mac/PC and upload the code.
Background
I was recently thinking of a way to track the number of times an RFID
module has been used, and to monitor the time at which it has. I happened
to think about Dropbox at the same time and decided to create an Arduino
Yun that parses RFID module operation data to a text file on Dropbox.
The Arduino Yun will monitor the amount of times that the RFID module
has been activated and if set up, IFTTT will send the user a notification
with the number of times that the module has been activated for.
RFIDDropboxLogger

SCHEMATICS
CODE

#define AIO_SERVER "io.adafruit.com"


#define AIO_SERVERPORT 1883
#define AIO_USERNAME "USERNAME" // TODO - insert
username
#define AIO_KEY "AIO KEY" // TODO - insert app key

#include <Bridge.h>
#include <Console.h>
#include <BridgeClient.h>
#include <SPI.h>
#include <MFRC522.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

#define SS_PIN 10
#define RST_PIN 5

uint32_t valueToSend; // the value to send to Adafruit IO


int proDebug = 1; // TODO - debugging?

BridgeClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER,
AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
MFRC522 mfrc522(SS_PIN, RST_PIN);

// Initialise Feeds
Adafruit_MQTT_Publish sendToDropbox =
Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME
"/feeds/sendToDropbox");
Adafruit_MQTT_Subscribe subscribeA =
Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME
"/feeds/subscribeA");

void MQTTConnect()
{
int8_t ret;

if(mqtt.connected()) // if already connected


{
return;
}

if(proDebug == 1)
{
Serial.println("Connecting to Server");
}

while((ret = mqtt.connect()) != 0) // attempt to connect


{
if(proDebug == 1)
{
Serial.print(" Error - ");
Serial.println(mqtt.connectErrorString(ret));
Serial.println(" Attempting Reconnection in 5 seconds");
}
mqtt.disconnect();
delay(5000);
}

if(proDebug == 1)
{
Serial.println(" Success - Connection Established");
Serial.println("Scan Card");
Serial.println("");
}
}

void setup()
{
Bridge.begin();
Console.begin();
SPI.begin();

if(proDebug == 1)
{
Serial.begin(9600);
while(!Serial) {};
}

mfrc522.PCD_Init();
delay(500);
mqtt.subscribe(&subscribeA); // start subscription
}

void loop()
{
MQTTConnect(); // connect to service

Adafruit_MQTT_Subscribe *subscription;
if(!mfrc522.PICC_IsNewCardPresent())
{
return;
}
if(!mfrc522.PICC_ReadCardSerial())
{
return;
}

String content = ""; // string to store card id

// store card id
for(byte i = 0; i < mfrc522.uid.size; i++)
{
// store the card id number in a variable
content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
content.concat(String(mfrc522.uid.uidByte[i], HEX));
}

valueToSend++; // increase value to trigger write

if(proDebug == 1)
{
Serial.print("Publishing ");
Serial.println(valueToSend);
}

Console.println(valueToSend);

if(!sendToDropbox.publish(valueToSend))
{
if(proDebug == 1)
{
Serial.println(F(" Error - Failed to Send Data"));
}
}
else
{
if(proDebug == 1)
{
Serial.println(F(" Success - Data Sent"));
}
}

if(! mqtt.ping()) // ping to keep server connection alive


{
if(proDebug == 1)
{
Serial.println(F("Error - Ping Failed"));
}
}

delay(500);
}
44) How to Make an Ultrasonic Ruller with Arduino and HC-SR04
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Breadboard (generic)

× 1
**Optional**

Ultrasonic Sensor - HC-SR04


(Generic)
Any ultrasonic sensor would × 1
work.

Jumper wires (generic)


Four would be enough
× 4

USB-A to B Cable
This will help you to connect the
× 1
laptop with Arduino

Laptop or computer
× 1
APPS AND ONLINE SERVICES
Arduino IDE
To program and upload to your arduino

ABOUT THIS PROJECT

Well I was sitting at home wondering how to measure how far away
things are without getting up of my couch. So I took a look at some
projects. They were pretty lit but they didn't have inches and
millimetres.

SCHEMATICS

Ultrasonic Ruler
Just wire the:

VCC of Ultrasonic sensor ---> 5V in Arduino


Trig of Ultrasonic sensor ---> Pin 2 in Arduino
Echo of Ultrasonic sensor ---> Pin 4 in Arduino
GND of Ultrasonic sensor ---> To GND in Arduino

And then just copy and paste the code above in your Arduino IDE. To
see the distance just go to Tools -> Serial Monitor or just put
Ctrl+Shift+M or for mac just Command+Shift+M.
CODE

const int trigPin = 2;


const int echoPin = 4;
void setup() {
Serial.begin(9600);}
void loop()
{
long duration, inches, cm, mm;
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2000);
digitalWrite(trigPin, HIGH);
delayMicroseconds(1000);
digitalWrite(trigPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
mm = microsecondsToMillimeters(duration);
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm, ");
Serial.print(mm);
Serial.print(" mm");
Serial.println();
delay(1000);
}
long microsecondsToInches(long microseconds)
{return microseconds / 74 / 2;}
long microsecondsToCentimeters(long microseconds)
{return microseconds / 29 / 2;}
long microsecondsToMillimeters(long microseconds)
{return microseconds / 2.9 / 2;}
45 Arduino Rural Hack Kit

COMPONENTS AND SUPPLIES

Arduino MKR1000

× 1

Arduino Rural Hack Kit


× 1
APPS AND ONLINE SERVICES
Arduino Web Editor

ABOUT THIS PROJECT


The Rural Hack kit.
The Rural Hack Kit is the perfect electronic set to get you started
hacking your farm, garden, or plants on your balcony.
The kit includes the essentials for monitoring the environment of our
green silent friends: an accurate soil moisture sensor, a precise digital
light sensor module, and a temperature and humidity sensor.
Moreover, to automate your greenhouse, the kit features a relay module
that you can use to control a water valve, a fan, or a lamp.
KIT CONTENTS
Humidity Sensor (DHT22)
Log-scale Analog Light Sensor (Ga1a12s202 in its Adafruit's
Flavour)
Soil Moisture Sensor (aka the slim chirp) from Miceuz
Grove Relay Module from Seeed
Resistors / pushbuttons / connectors
This is the first of a series of tutorial that will teach how to use the
modules in the kit. In this tutorial we are going to learn how to connect
the sensors and actuators to the Arduino, read their data, and interact
with them.
In the next tutorials you will learn how to connect the sensor to cloud
services and take care of your garden remotely.
DHT22 humidity and temperature sensor
Sensor Specs
The DHT22 is a digital sensor capable of reading environmental
temperature and humidity.
Low cost
3 to 5V power and I/O
2.5mA max current use during conversion (while requesting data)
Good for 0-100% humidity readings with 2-5% accuracy
Good for -40 to 80°C temperature readings ±0.5°C accuracy
No more than 0.5 Hz sampling rate (once every 2 seconds)
Body size 27mm x 59mm x 13.5mm (1.05" x 2.32" x 0.53")
4 pins, 0.1" spacing
Weight (just the DHT22): 2.4g
Connections
Connecting to to the sensor is very easy. As shown in the picture
connect
the first pin to VCC on your board.
The second pin is the data Out pin, connect that to any digital pin on
the board.
leave the third pin disconnected.
connect the forth pin to ground.
Setup & test
Before you can try the sensor you need to install its library. Search for
dht on the library manager and install the library.
Now you can just upload the test sketch that will get the data from the
sensor and print them to the serial port.
#include <SimpleDHT.h>
// for DHT22,
// VCC: 5V or 3V
// GND: GND
// DATA: 6
int pinDHT22 = 6;
SimpleDHT22 dht22;
void setup() {
Serial.begin(115200);
}
void loop() {
// start working...
Serial.println("=================================");
Serial.println("Sample DHT22...");
// read without samples.
// @remark We use read2 to get a float data, such as 10.1*C
// if user doesn't care about the accurate data, use read to get a byte data, such as 10*C.
float temperature = 0;
float humidity = 0;
int err = SimpleDHTErrSuccess;
if ((err = dht22.read2(pinDHT22, &temperature, &humidity, NULL)) !=
SimpleDHTErrSuccess) {
Serial.print("Read DHT22 failed, err="); Serial.println(err);delay(2000);
return;
}
Serial.print("Sample OK: ");
Serial.print((float)temperature); Serial.print(" *C, ");
Serial.print((float)humidity); Serial.println(" RH%");
// DHT22 sampling rate is 0.5HZ.
delay(2500);
}
You can now open the serial monitor and you should be able to see the
temperature and humidity value printed there.
I2C Soil moisture sensor
The soil moisture sensor provided with the kit is probably one of the
most reliable and at the same time cheap sensor for DIY soil moisture
measurement on the market.
Classic soil moisture sensor, (the one that look like a fork with two
electrodes) measure resistance between the two electrodes planted in
the soil; High resistance between the electrodes means that the soil is
not conducting electricity therefore it is probably dry; low resistance
means that the electricity is flowing easily between the two electrodes,
that's what happens when the sensor is in water or in a wet soil.
The downside of the described techniques is that the copper on the
electrodes quickly get rusty, hence after a while, the reading from those
sensor become not accurate anymore.
The sensor provided in the kit, uses capacitive sensing to measure the
capacitance of the medium it's surrounded by: Wet soil for instance has
a higher capacitance than dry soil or air. Instead of electrodes it
features a capacitive antenna that doesn't need to stay in direct contact
with the soil, this protects the sensor making it's reading reliable and
accurate in time.
The sensor can be read via I2C protocol and provides these features:
Soil moisture sensing
Light sensing
Temperature sensing
Reset chip
I2C address change
Deep sleep
Sensor Specs
Version 2.7.5
Supply voltage 3.3V - 5V
Current consumption: 1.1mA @ 5V, 0.7mA @ 3.3V when idle,
14mA @ 5V, 7.8mA @ 3.3V when taking a measurement. When
constantly polling sensor at full speed, current consumption averages
to 4.5mA @ 5V, 2.8mA @ 3.3V
Operating temperature 0°C - 85°C
Moisture reading drift with temperature - <10% over full temp range
Don't forget to provide pullups for SCL and SDA lines
Default I2C address is 0x20 (hex)
Connections
The connection to the sensor is done via i2c, depending on the board
you are using you might have different pin assigned to I2C;
If you are workng with a MKR1000 connect:
VCC to VCC
GND to GND
SCL to 12
SDA to 11

Setup & test


First of all install the I2CSoilMoistureSensor Library: open the library
manager, search for I2CSoilMoistureSensor and install the library.
Upload now the example sketch and you should be able to see the
measured data.
#include <I2CSoilMoistureSensor.h>
#include <Wire.h>
I2CSoilMoistureSensor sensor(0x60);
void setup() {
Wire.begin();
Serial.begin(9600);
sensor.begin(); // reset sensor
delay(1000); // give some time to boot up
Serial.print("I2C Soil Moisture Sensor Address: ");
Serial.println(sensor.getAddress(),HEX);
Serial.print("Sensor Firmware version: ");
Serial.println(sensor.getVersion(),HEX);
Serial.println();
}
void loop() {
while (sensor.isBusy()) delay(50); // available since FW 2.3
Serial.print("Soil Moisture Capacitance: ");
Serial.print(sensor.getCapacitance()); //read capacitance register
Serial.print(", Temperature: ");
Serial.print(sensor.getTemperature()/(float)10); //temperature register
Serial.print(", Light: ");
Serial.println(sensor.getLight(true)); //request light measurement, wait and read light
register
sensor.sleep(); // available since FW 2.3
}
GA1A12S202 Log-scale Analog Light Sensor
This very cheap sensor module produced by Adafruit it’s considerably
more accurate that a old fashion photo-resistor you might have used in
other project.
Most light sensors have a linear relationship with light levels, which
means that they're not very sensitive to changes in darkened areas and
'max' out very easily when there's a lot of light.
This sensor is logarithmic over a large dynamic range of 3 to 55,000
Lux, so it has a lot of sensitivity at low light levels but is also nearly
impossible to "max out" so you can use it indoors or outdoors without
changing code or calibration.
Sensor Specs
Power with 2.3-6V
Onboard 68K load resistor for max 3V analog output
0.2 grams
0.4” x 0.5" x 0.06" (10mm x 13mm x 1.5mm)
0.1” (2.5mm) mounting hole
Connections
Reading the light intensity with this sensor is is as easy as reading a
analog from an analog sensor.
Just connect the power via the VCC and GND, and connect the OUT
pin to a analog input on your board.
VCC to 3.3V or 5V depending on your board voltage
OUT to AO on your board
GND to GND on your board
Setup & test
You won’t need any library to use it just read the value from the A0 pin
using analogueRead() function.
Max output value of this sensor is 3.3V, If you are using a 3.3V board
like the mkr1000 you should have accurate readings out of the box.
A simple conversion from analogue readings to lux is done in the
provided example sketch below.
Upload it to your board and you should be able accurately measure the
light in the room.
/*
Test sketch for the Adafruit Analog Light Sensor
by Bill Earl
for Adafruit Industries
Connect sensor output to Analog Pin 0
Connect VCC to VCC and GND to GND
*/
int sensorPin = A0; // select the input pin for the potentiometer
float rawRange = 1024; // 3.3v
float logRange = 5.0; // 3.3v = 10^5 lux
void setup()
{
analogReference(EXTERNAL); //
Serial.begin(9600);
Serial.println("Adafruit Analog Light Sensor Test");
}
void loop()
{
// read the raw value from the sensor:
int rawValue = analogRead(sensorPin);
Serial.print("Raw = ");
Serial.print(rawValue);
Serial.print(" - Lux = ");
Serial.println(RawToLux(rawValue));
delay(1000);
}
float RawToLux( int raw)
{
float logLux = raw * logRange / rawRange;
return pow(10, logLux);
}
groove relay
The last important piece of the kit is the relay. The relay is an
electromechanical component that you can use to control big loads
from your Arduino. You can attach water pumps, fans and basically
anything that can be switched on or off.
!!! watch out !!! connecting big loads like 220V lamps is dangerous!!!
Adopt all the required precautions if you are working with more than
120V.
the relay provided in the kit can be controlled also by a 3.3v devices, it
is therefore very easy to connect it to a MKR1000.
Connections
Connecting the relay to the Arduino is very simple, just connect the 3
wires that come with it to the Arduino.
VCC to VCC
GND to GND
SIG to pin9 on the Arduino.
The two screw terminal on the module are where you should attach
your load: a fan a pump, a light-strip or anything else.

Setup & test


To test that everything is working correctly we are just going to upload
a blink sketch on our board.
Every time the led switch on or off you should hear a mechanical noise
inside the relay housing.
int RELAY_PIN=9;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
// initialize digital pin RELAY_BUILTIN as an output.
pinMode(RELAY_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
pinMode(RELAY_PIN, HIGH); // open the circuit
delay(1000);
digitalWrite(LED_BUILTIN, LOW); // close the circuit
pinMode(RELAY_PIN, LOW);
delay(1000); // wait for a second
}

SCHEMATICS

/*
-
CODE

#include <I2CSoilMoistureSensor.h>
#include <Wire.h>
#include <SimpleDHT.h>

int pinDHT22 = 6;
SimpleDHT22 dht22;

int sensorPin = A0; // select the input pin for the ga1a light sensor

I2CSoilMoistureSensor soilMoistureSensor(0x60);
float rawRange = 1024; // 3.3v
float logRange = 5.0; // 3.3v = 10^5 lux

float soilTemperature;
int soilMoisture;

int lightValue;

float airTemperature;
int airHumidity;

void setup() {
Wire.begin();
Serial.begin(9600);

soilMoistureSensor.begin(); // reset sensor


delay(1000); // give some time to boot up
Serial.print("I2C Soil Moisture Sensor Address: ");
Serial.println(soilMoistureSensor.getAddress(),HEX);
Serial.print("Sensor Firmware version: ");
Serial.println(soilMoistureSensor.getVersion(),HEX);
Serial.println();
}
void loop() {

///////////////////////////////////////////////
//get all the data from the soul moisture sensor
///////////////////////////////////////////////
while (soilMoistureSensor.isBusy()) delay(50); // available since FW
2.3
soilMoisture=soilMoistureSensor.getCapacitance();
soilTemperature=soilMoistureSensor.getTemperature()/(float)10;
soilMoistureSensor.sleep(); // available since FW 2.3

///////////////////////////////////
//get the data from the dht sensor
///////////////////////////////////

float temperature = 0;
float humidity = 0;
int err = SimpleDHTErrSuccess;

if ((err = dht22.read2(pinDHT22, &temperature, &humidity, NULL))


!= SimpleDHTErrSuccess) {
Serial.print("Read DHT22 failed, err=");
Serial.println(err);delay(2000);
return;
}
airTemperature=(float)temperature;
airHumidity=(float)humidity;

///////////////////////////////////
//get the data from the light sensor
///////////////////////////////////
int rawValue = analogRead(sensorPin);
lightValue=RawToLux(rawValue);

void printValue(){
Serial.print("Soil Moisture Capacitance: ");
Serial.print(", Temperature: ");
Serial.print(", Light: ");
}

float RawToLux(int raw){


float logLux = raw * logRange / rawRange;
return pow(10, logLux);
}

46) Arduino Only Three Pins for a 4X3 Keypad


COMPONENTS AND SUPPLIES
Resistor 330 ohm

× 1

Resistor 1k ohm

× 3

Resistor 3k ohm
× 1
4x3 matrix 12 key array switch
keypad × 1

Arduino UNO & Genuino UNO

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Introduction
The aim of this project is to significantly reduce the number of pins
required by a numeric keypad. This is because we often need many I/O
pins compared to those available on the Arduino Uno or Nanoboards.
The ordinary numerical keypads are structured in matrix: a 4x3 keypad,
requires 4+3 Arduino digital pins. Numerous libraries are available on the
net to use it with Arduino.
My Solution
The solution I propose is much better because it uses only three analog
inputs, with a circuit like the one shown in thefollowing figure.
For each column there are only 4 voltage values, corresponding to each of
the 4 keys, plus zero volts in case no key is pressed. In the equivalent
scheme (b) the R1e indicates one of the four resistors R1-R4, while R2e is
one of the three resistors R5-R7.
Now let's see how to make the four widest possible intervals. First of all
the resistors R2e = R5 = R6 = R7 can be made equal, then we can set R1 =
0 to have the outputs corresponding to the first line at 5V.
With R2=330 ohm, R3= 1 k ohm, R4= 3 k ohm and R5, R6, R7= 1 k ohm,
the following intervals are obtained for each output:
As you can see, the intervals on the threeoutputs are the largest possible
and you can use six standard resistors with atolerance of ±5%. With an
extra analogue input and another resistor, a 4x4keyboard can be used and
so on. The following figure shows the connections withArduino.

In the diagram the resistor R1 is connected toline 2 because the one on line
1 has drawn it with a wire, so the resistorreferences have been scaled by
one. Pin assignments can be modified accordingto needs, as long as they
are pin configurable as analog.
Of course, if Arduino is powered at 3.3V, nothing would change because
the ADC converter as default uses the supplyvoltage and the ADC
numbers don’t change.
To test the program, not having a keyboardof this type, I built it with
recycled keys, the figure below shows myprototype. The 5-pin right
connector is used to wire it to Arduino.
SCHEMATICS

CODE
// limits of keyboard output values:
const int NADCm100[4] = {923,669,412,156};
const int NADCp100[4] = {1123,869,612,356};
const char key[13] = {'1','4','7','C','2','5','8','0','3','6','9','E'};
int keyval[3];
int i,colp,val;

void setup(){
Serial.begin(9600); // used with serial monitor
}

void loop() {
char k;
k = KeyPad();// read keypad
if (k != 'N'){ // a key was pressed
Serial.print("key = ");
Serial.println(k);
delay(500);
}
}

/******** Functions used by program ********/


char KeyPad(){
// read keypad and return the char key
// key = 'N' for none
KeyScan();// read analog keyboard
if (keyval[0]+keyval[1]+keyval[2] < 40) {
return 'N';
}
else { // a key was pressed
delay(10);// antibounce
KeyScan();// reread analog keyboard
for (i=0; i < 3; i++){//identify which column it belongs to
if (keyval[i] > 40){
colp= i;
val= keyval[i];// this is the corresponding value
for (int j=0; j < 4; j++){// identify which key was pressed on the column
if (val >= NADCm100[j] && keyval <= NADCp100[j]){
return key[colp*4+j];
break;
}
}
}
}
}
}

void KeyScan(){// read analog keyboard


keyval[0]= analogRead(A0);
delay(1);
keyval[1]= analogRead(A1);
delay(1);
keyval[2]= analogRead(A2);
delay(1);
}
47) Retro Computing with Arduino Mega and a Z80 Processor

COMPONENTS AND SUPPLIES

Arduino Mega 2560 & Genuino


Mega 2560
× 1

Z80 Processor
× 1
Breadboard (generic)

× 1

Jumper wires (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


One day when I tidied up my cellar, I found a Z80 chip from an old
computer. In the '80s and '90s, this processor was very popular, and I
dare to say the most popular processor ever. So I got the idea to breathe
new life into it.
The Z80 has a tinker-friendly 40-pin DIP housing, but unlike modern
tinker-friendly Processors like the ATmegas, there is no built-in RAM,
program flash or any peripherals. It has only the raw core functionality
of every Processor, which is to make basic calculations on some bits
and bytes.
With a bunch of jumper wires, a small breadboard and an Arduino
Mega that emulates ROM, RAM and serial IO, I made a fully fledged
Z80-based computer!
This is just an academical fun project without any practical relevance,
but it teaches you how microprocessors still work in detail!

SCHEMATICS
CODE
z80-test.inoC/C++

#include "memory.h"

/*Wiring:
Address Lines:
Arduino Pin 22..29 <---> Z80 A0..A7

Data Lines:
Arduino Pin 49..42 <---> Z80 D0..D7

Control lines:
Arduino Pin 10 <---> Z80 Pin 6 (CLK)
Arduino Pin 19 <---> Z80 Pin 21 (RD)
Arduino Pin 18 <---> Z80 Pin 22 (WR)
Arduino Pin A9 <---> Z80 Pin 19 (MREQ)
Arduino Pin A10 <---> Z80 Pin 20 (IORQ)
Arduino Pin 40 <---> Z80 PIN 26 (RESET)
*/

//Working memory
uint8_t memory[1024];

//Z80 Out
//Port D
#define RD_PIN PD2 //(INT2 - Arduino Pin 19) Z80 Pin21
#define WR_PIN PD3 //(INT3 - Arduino Pin 18) Z80 Pin 22
#define RD ((PIND & (1 << RD_PIN)) == 0)
#define WR ((PIND & (1 << WR_PIN)) == 0)
#define PORT_MASK_D ~((1 << RD_PIN) + ( 1 << WR_PIN));

//Port K
#define MREQ_PIN PK1 //(PCINT17 - Arduino Pin A9) Z80 Pin 19
#define IORQ_PIN PK2 //(PCINT18 - Arduino Pin A10) Z80 Pin 20

#define MREQ ((PINK & (1 << MREQ_PIN)) == 0)


#define IORQ ((PINK & (1 << IORQ_PIN)) == 0)

#define ADDR PINA //A0..A7


#define ADDR_HI (PINC & (PC0 | PC1)) //A8..A9

//Z80 In
//PortB
#define CLK_PIN PB4 //(OC2A) Z80 Pin 6
//Port G
#define INT_PIN PG0 //Z80 Pin 16, Arduino Pin 41
#define RST_PIN PG1 //Z80 PIN 26, Arduino Pin 40
#define WAIT_PIN PG2 //Z80 Pin 24, Arduino Pin 39
#define RESET(b) b == 0 ? PORTG |= (1 << RST_PIN) : PORTG &= ~(1 << RST_PIN);
#define PORT_MASK_G (1 << INT_PIN) + (1 << RST_PIN) + (1 << WAIT_PIN);

// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200);
const long fClk = 1E5;
//Serial.begin(256000);
DDRA = 0x00; //Port A (Addr Low) input
DDRC = 0x00; //Port C (Addr Hi) input
DDRD &= PORT_MASK_D;
DDRK = 0x00; //Port K Input (Z80 sysctl out)
DDRG |= PORT_MASK_G;
PORTG |= PORT_MASK_G;
DDRL = 0xff; //Data Bus
PORTL = 0x00;

//Pin Interrupts
EICRA |= (1 << ISC31) + (0 << ISC30) + (1 << ISC21) + (0 << ISC20);
EIMSK |= (1 << RD_PIN) + (1 << WR_PIN);

//Clock Timer2
DDRB |= (1 << CLK_PIN); //Output
TCCR2A = (0 << COM2A1) + (1 << COM2A0); //Toggle OC2A on Compare Match
TCCR2A |= (1 << WGM21); //CTC Mode
TCCR2B = (0 << CS22) + (0 << CS21) + (1 << CS20); //No Prescaling
OCR2A = 16E6 / (2 * fClk) - 1;

memset(memory, 0, sizeof(memory));
memcpy(memory, mem, sizeof(mem));

RESET(1);
delay(1);
RESET(0);
}

// the loop is empty, because this is interrupt-driven


void loop() {}

//Read data from Data Bus


inline uint8_t DATA_GET() {
DDRL = 0;
return PINL;
}

//Write data to Data Bus


inline void DATA_PUT(uint8_t d) {
DDRL = 0xff;
PORTL = d;
}

ISR(INT2_vect) {//CPU Reads


//Serial.println(ADDR);
if (MREQ) {
DATA_PUT(memory[ADDR]);
}
}

ISR(INT3_vect) {//CPU Writes


if (MREQ) {
memory[ADDR] = DATA_GET();
}
else {//IORQ
Serial.print((char)DATA_GET());
}
}

memory.hC/C++ code
#ifndef MEMORY_H
#define MEMORY_H

uint8_t mem[] = {
0x21, 0x0a, 0x00, //ld hl, ??
0x0e, 0x00, //ld c, 0
0x06, 0x0c, //ld b, 12
0xed, 0xb3, //otir
0x76, //halt
'H','e','l','l','o', ' ','W','o','r','l','d','\n'
};

#endif

48) Arduino Electronic Chameleon


COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

Adafruit NeoPixel Ring: WS2812 5050 RGB


LED
× 1

TCS 3200 Colour sensor


× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Ever wondered how the chameleon changes its colour through the
changes in environmental colours?
There's something called Melanocyte Stimulating Hormone or MSH. If
you want to dig more into this please follow this link. The stories apart,
I wanted to build ambient lighting system or something like the
chameleon. This looks cool and also it helps eyes. I had a NeoPixel
LED strip and a spare colour sensor. So I just built my Chameleon
(electronic) using Arduino (microcontroller for everyone) as the brain.
Step 1: Things You Will Need
1. Arduino Nano (any Arduino is fine)
2. Colour Sensor TCS3200
3. NeoPixel LED Strip
4. Jumper wires and power source
Step 2: Brief Intro to Parts
Arduino: Microcontroller which gets the RGB colour sensor data from
TCS 3200 and generates the respective PWM signal to control the
colour of NeoPixel LED Lights. TCS 3200 Colour Sensor: This sensor
contains an array of photodiodes which respond differently to different
colours hence it gives out the colour of light falling on the photodiode
array. This data can be used to replicate those colours.Neo Pixel LED:
This can generate a lot of colours based on the signal given to it. The
name of the IC is WS2812B.
Step 3: Connecting Everything
Connection - Reaction..The connection has to be done in such a way
that Arduino has to read the data from 4 different photodiodes in the
TCS 3200. And reflect back those value as data to NeoPixel LEDs to
replicate the same colour. 4 photodiodes on the sensors are sensitive to
4 different colour combinations. These produce current signals which
are converted into frequency signals i.e I to F conversionThis is read by
Arduino pins and then given as input to the NeoPixel LEDs.I don't
want to go deep into the working of sensors. This can be understood by
referring the data sheets of TCS 3200 sensor.
Step 4: Coding
The code for this project is here.
You can download this and unzip the file to find necessary libraries and
code. Please put the libraries into the libraries folder of Arduino IDE.
The compile the code and upload it.The code is self-explanatory. I
improve my coding by looking at others codes. Any suggestions to
optimise the code are always welcome.
Step 5: Viola... It Works
Here it works. It's now replicating any colours you are showing it to the
sensor. Good applications are
1. Ambient lighting for TVs and PCs, this reduces eye strain as it
mimics maximum colour in your screen.
2. Room lighting
3. Mood lighting
4. You can 3D print a chameleon and place all electronics to make it as
a real 3D printed chameleon.

SCHEMATICS

CODE
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

// Which pin on the Arduino is connected to the NeoPixels?


#define PIN 9

// How many NeoPixels are attached to the Arduino?


#define NUMPIXELS 5

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN,


NEO_GRB + NEO_KHZ800);

int delayval = 333; // delay

#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8

int frequency = 0;
int Red, Green, Blue;

void setup() {
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
pinMode(sensorOut, INPUT);

// Setting frequency-scaling to 20%


digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);

Serial.begin(9600);
pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {
// Setting red filtered photodiodes to be read
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
// Reading the output frequency
frequency = pulseIn(sensorOut, LOW);
//Remaping the value of the frequency to the RGB Model of 0 to 255
frequency = map(frequency, 25,72,255,0);
if (frequency < 0) {
frequency = 0;
}
if (frequency > 255) {
frequency = 255;
}
Red= frequency;
// Printing the value on the serial monitor
Serial.print("R= ");//printing name
Serial.print(frequency);//printing RED color frequency
Serial.print(" ");
delay(100);

// Setting Green filtered photodiodes to be read


digitalWrite(S2,HIGH);
digitalWrite(S3,HIGH);
// Reading the output frequency
frequency = pulseIn(sensorOut, LOW);
//Remaping the value of the frequency to the RGB Model of 0 to 255
frequency = map(frequency, 30,90,255,0);
if (frequency < 0) {
frequency = 0;
}
if (frequency > 255) {
frequency = 255;
}
Green = frequency;
// Printing the value on the serial monitor
Serial.print("G= ");//printing name
Serial.print(frequency);//printing RED color frequency
Serial.print(" ");
delay(100);
// Setting Blue filtered photodiodes to be read
digitalWrite(S2,LOW);
digitalWrite(S3,HIGH);
// Reading the output frequency
frequency = pulseIn(sensorOut, LOW);
//Remaping the value of the frequency to the RGB Model of 0 to 255
frequency = map(frequency, 25,70,255,0);
if (frequency < 0) {
frequency = 0;
}
if (frequency > 255) {
frequency = 255;
}
Blue = frequency;
// Printing the value on the serial monitor
Serial.print("B= ");//printing name
Serial.print(frequency);//printing RED color frequency
Serial.println(" ");
pixels.setPixelColor(0, pixels.Color(Red,Green,Blue)); // Moderately
bright green color.
pixels.setBrightness(64);
pixels.show(); // This sends the updated pixel color to the hardware.
delay(100);
}
49) Door Alarm Sensor with Arduino
COMPONENTS AND SUPPLIES
Arduino Nano Every

× 1

SparkFun Solder-able Breadboard -


Mini
× 1
I will be using a white one.

Buzzer, Piezo
× 1

9V battery (generic)

× 1

Male/Female Jumper Wires

× 1

9V Battery Clip

× 1

Reed Switch, SPST-NO

× 1
APPS AND ONLINE SERVICES

Arduino IDE

ABOUT THIS PROJECT


So, in this proyect, we will make a sensor for your door. We will
programe it so that when the door closes, It plays La Cucaracha. We will use a
function called tone.

SCHEMATICS
CODE
int times = 150;
int times2 = 75;
int times3 = 133;

void setup() {
// put your setup code here, to run once:
pinMode(9,INPUT);
pinMode(LED_BUILTIN,OUTPUT);

void loop() {
// put your main code here, to run repeatedly:
int sensorValue = digitalRead(9);

if (sensorValue == HIGH){
digitalWrite(LED_BUILTIN,HIGH);
// Get ready for... LA CUCARACHA
tone(8,261,times2); //First part
delay(times);
tone(8,261,times2);
delay(times);
tone(8,261,times2*1.5);
delay(times);
tone(8,349,times2*2);
delay(times*1.5);
tone(8,440,times2);
delay(times);
tone(8,261,times2);
delay(times);
tone(8,261,times2);
delay(times);
tone(8,261,times2);
delay(times);
tone(8,349,times2*2);
delay(times*1.5);
tone(8,440,times2);
delay(times*2);

tone(8,349,times2); //Second part


delay(times3);
tone(8,349,times2);
delay(times3);
tone(8,329,times2);
delay(times3);
tone(8,329,times2);
delay(times3);
tone(8,293,times2);
delay(times3);
tone(8,293,times2);
delay(times3);
tone(8,261,times2*2);
delay(times*3);
}else{
digitalWrite(LED_BUILTIN,LOW);
}
delay(10);
}
50) Arduino Neopixel Motion Activated Nihht Light

COMPONENTS AND SUPPLIES


Resistor 1k ohm
× 1

Ultrasonic Sensor
× 1

Arduino UNO & Genuino UNO

× 1

Jumper wires (generic)

× 1

9V 1A Switching Wall Power


Supply
× 1

NeoPixel strip

ABOUT THIS PROJECT


It's finally working! Took so many code rewrites.
Background
I am new to all of this open source electronics DIY stuff. I am a moderator
for Hackster.io, and as a result, have become interested in the projects I
review. I decided to make a motion activated night light for my bathroom.
This way I don't have to turn on the bathroom light in the middle of the
night, blinding myself every time go tinkle.
Introduction
I grabbed code from a few sources and compiled them together to make
the attached code. With Ingo Lohs help, I saw where I was making a
mistake. I was doing strip.clear, but not strip.show afterwards. Now it
works like a beauty. I used hardware that I had laying around. No motion
sensor was available, hence the Ultrasonic sensor.
Steps
connect the Ultrasonic sensor Grd to UNO Grd
solder wires to Neopixel Grd, 5v, and Din
plug Neopixel Grd wire to Grd on UNO
join and solder Neopixel 5v wire and Ultrasonic sensor vcc to resistor to UNO 5v
connect Ultrasonic sensor Trig to UNO pin 2
connect Ultrasonic sensor Echo to UNO pin 3
connect Neopixel Din to UNO pin 12
Upload sketch

Summary
After a few easy connections to the UNO, you have a pretty night light
that will activate when you walk in front of the Ultrasonic sensor. I hope
this has helped those of you that want to use an Ultrasonic sensor as a
motion detector. Adjust the distance for activation by altering the "if" loop
cm = _____.
SCHEMATICS
CODE
#include <Adafruit_NeoPixel.h>
#define LEDPIN 12 // connect the Data from the strip to this pin on the Arduino
#define NUMBER_PIEXELS 43// the number of pixels in your LED strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMBER_PIEXELS, LEDPIN, NEO_GRB
+ NEO_KHZ800);
const int TrigPin = 2;
const int EchoPin = 3;
float cm;
int delayTime = 200;
int wait = 500;
int i = 0;

void setup()
{
Serial.begin(9600);
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
strip.begin();

}
void loop()
{

digitalWrite(TrigPin, LOW);
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(TrigPin, LOW);
cm = pulseIn(EchoPin, HIGH) / 58.0; //The echo time is converted into cm
cm = (int(cm * 100.0)) / 100.0; //Keep two decimal places
Serial.print("Distance\t=\t");
Serial.print(cm);
Serial.print("cm");
Serial.println();

if (cm <100){

for (int i=0; i<strip.numPixels()-1; i++) {


// starting at i, draw the 7 color rainbow}
// a seven segment rainbow with red on the highest pixel
void rainbow7(uint16_t i, uint16_t wait) ;
int np = strip.numPixels(); // we use the modulo function with this
strip.setPixelColor(i % np, 0, 0, 0); // off
strip.setPixelColor((i+1) % np, 25, 0, 25); // violet
strip.setPixelColor((i+2) % np, 255, 0, 255); // indigo
strip.setPixelColor((i+3) % np, 0, 0, 150); // blue
strip.setPixelColor((i+4) % np, 0, 150, 0); // green
strip.setPixelColor((i+5) % np, 255, 255, 0); // yellow
strip.setPixelColor((i+6) % np, 110, 70, 0); // orange
strip.setPixelColor((i+7) % np, 150, 0, 0); // red
strip.show();
delay(wait);
strip.clear();
strip.show();}}
else{
strip.clear();
strip.show();
}

51) Arduino Easy Iot Water Leakage Indicator


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Espressif ESP8266 ESP-01


× 1

SmartThings Samsung SmartThings


Water Leak Sensor
× 1

7805 Voltage Regulator IC


× 1

9v Battery
× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

EasyIOT Server

ABOUT THIS PROJECT


This project will keep you aware about leakage of water from pipe or
tank. Leaks from pipes, plumbing fixtures and fittings are a significant
source of water waste for many households. Research has shown that
the typical home can lose 2,000 to 20,000 gallons of water per year due
to leaks. Some leaks are obvious, such as dripping faucets and leaking
water heaters. Unfortunately, many leaks go undetected for years
because the source of the leak is not visible.
Step 1: Power Supply

Here we will use 9v battery for power supply. We will need 7805
voltage regulator IC to get 9V. Then from 7805 IC, feed it to Arduino.
Step 2: Connecting ESP266 and powering it

Connect the Arduino’s 3v3 (3.3V) output to ESP8266. The ESP8266


works with 3.3V and not 5V, so this is necessary.
Step 3: Connect RX and TX

Connect the RXD pin of the Arduino to the RX pin of the


ESP8266.Connect the TXD pin of the Arduino to the TX pin of the ESP.
When we want two things to talk to each other over serial, we connect
the TX pin of one to the RX of the other (send goes to receive and the
opposite). Here we do not have the Arduino talk to the ESP8266 though,
our computer is talking to it via the Arduino.
Step 4: GND and RST

Connect the RES or RESET pin, When you ground the reset pin, the
Arduino works as a dumb USB to serial connector, which is what we want
to talk to the ESP8266.
Step 5: Connecting Water Leak Sensor
Next we connect Ardino and water sensor. We connect Arduino VCC
and GND to water sensor VCC and GND. Arduino digital Pin 2 is
connected to digital out pin of water sensor.
Now Upload Code.
Step 6: EasyIOT Server
We have To make Our IOT Server which Can be found on link
here: https://iot-playground.com/download

SCHEMATICS
CODE
#include <Esp8266EasyIoT.h>
#include <SoftwareSerial.h>

Esp8266EasyIoT esp;

SoftwareSerial serialEsp(10, 11);

#define LEAK_PIN 2 // Arduino Digital I/O pin number


#define CHILD_ID_LEAK 0
Esp8266EasyIoTMsg msgLeak(CHILD_ID_LEAK,
V_DIGITAL_VALUE);
//Esp8266EasyIoTMsg msgHum(CHILD_ID_LEAK, V_LEAK); //
supported in esp >= V1.1 lib

int lastLeakValue = -1;

void setup()
{
serialEsp.begin(9600);
Serial.begin(115200);

Serial.println("EasyIoTEsp init");
esp.begin(NULL, 3, &serialEsp, &Serial);

pinMode(LEAK_PIN, INPUT);

esp.present(CHILD_ID_LEAK, S_LEAK);
}

void loop()
{
esp.process();

// Read digital pin value


int leakValue = digitalRead(LEAK_PIN);
// send if changed
if (leakValue != lastLeakValue) {
Serial.println(leakValue);
esp.send(msgLeak.set(leakValue==0?0:1));
lastLeakValue = leakValue;
}
}
52) Arduino Climate Cube for Greenhouse

COMPONENTS AND SUPPLIES


Arduino MKR1000
You can find a BOM file for full
× 1
list of components

1,3" OLED I2C display


× 1
2-channel Opto-isolate Relay
Module × 1

5V DC power supply
× 2

DS3231 clock
× 1

RGB Diffused Common Cathode

× 1

Limit switch with NO and NC


connection × 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

2 years ago I decided to step to a new level in controlling micro-


climate in our thermal water heated greenhouses. Before that time for
example we did all airing by opening-closing windows manually. It
was a waste of time, took hours per day! So the "simple" and clear step
was to build automatic micro-climate control "things" begin with
automatic windows openers.
The physical environment (from big to small):
Production environment (there are 3x2000 m2 different places but
basics are the same)
3-phase motor, worm gear unit with two drums
One window faced to North

The other faced South


200 meters long, 10 meters wide and 4 meters high half-circle
production area
Any number (26 in my case) of windows along at the top of the
structure
400 (2x200) meters long, 4mm thick steel leading wire to attach to
the control arms of the windows. One of the 200m line is the
opening line the other is the closing line.
The leading wire is attached to a 3-phase motor assembled with a
worm gear unit. The steel wire lines are twisted around the axis of
the gear unit clockwise and counter-clockwise. If the motor rotates
clockwise then one line of wire moves one direction and the other
one moves opposite.
Different rotation is managed by a 3-pole reversing contactor
assembled with a thermal relay set to the motor's parameters. The
contactor has two 24V AC coils. Coils can be powered with a 230AC
to 24V AC transformer through a 3-way selector switch (OPEN or
CLOSE) where the third position is for the AUTOMATIC control.
For limiting the amount of opening and closing movement (no to
destroy the structure by the gear) two limit switches have been put
near the steel wire rail.
BIG "How to" questions for automatic micro-climate control
... How to decide what kind of climate is need for the plants during
24 hours whole year...?
... How to manage system stability in an airspace where humidity
can be 100%, temperature can be 60 Celsius degree and huge EMI
pollution (3-phase motor, contactor, pumps and relays for irrigation,
etc.) all around...?
... How to protect structure, and parts if malfunction hits...? Have
experienced when a motor-gear-unit crushes the structure. No one
should see that...
Etc...
A little recollection
Final and stable assembly before Climate Cube
During last 2 years I had several phases of this project. For example it
was a dead end using plastic cases. High humidity and sunlight can be
harmful. All the 1602 and 2004 type LCDs with its HD44780 type
controller have a high sensitivity to any kind of electromagnetic
impact. After a time it just doodled random things. Not to think for
future modifications can be expensive. Bought many Arduino Nanos
thinking they are just fine but later I built around the MKR1000 boards.
Yes they are much expensive but for IoT projects being online is
essential :) isn't it?
Path believed quite good
After this long prelude lets do the workmanship (from big to small
again).
I need to isolate things as much as possible from climate. Metal box is
the best option i found to achieve that. I have to separate high voltage
things (Supply Box) from low voltage (MCU Box) things. Two metal
boxes better than one :).

The high voltage box contains the 3-phase input supply (3 phase +
Neutral + Earth). Circuit brakers for motor/transformer and for MCU in
the other box. Transformer (230V to 24-18-12-6-3V). Reversing
contactor and thermal relay. Input and output cables from motor to
Supply Box, from MCU box to Supply Box.
The biggest limitation is the physical size of the controller housing.
First it was a headache how to install everything in a logical manner.
The MCU Box contains the controller aka the Climate Cube, and an
I2C bus expander housing. The controller have all the stuff what counts
here. But first, the most important thing is I wanted to built it as a
structure of modules to be able to expand, enhance later and replace
parts if necessary. See the wiring diagram.
MKR1000 has everything (now) i need. Lots of GPIOs, hardware I2C,
WIFI option, and strong processing ability not to mention it has more
program space than Nanos.
Connection between circuit boards by wires
I use 2-channel opto-isolated relay to switch the 24V AC circuit to
drive the contactors' coil. The relay can be fully separated from the
MCU by giving a second 5V DC power supply. So the coil of the relay
powered from one power supply (PSU) and the optocouplers (relay
inputs' VCC) are from another PSU shared with MCU. The two PSUs
have been built with input and output EMI filter circuits. (I did not find
such filtered PSU where 24V AC input available).
A DS3231 clock is installed also. During plant production there are
many scenarios. For example if there is not enough sunlight for plants
to do their photosynthesis effectively no need to keep hotter air.
The lack of sunlight in the winter (January) not warmth the air and
there is a high chance that temperature inside is lower than what we
wanted so windows stay closed. If this happens plant cannot get fresh
CO2 rich air. So we need to get some fresh air in despite the
temperature inside still lower what needed. Of course we don't want to
do that in the night when outer temperature drops minuses. That is why
MCU needs to know what time it is. Because, for the daylight I need to
set checkpoint/time. Example: when certain conditions appear MCU
opens the windows for 5 seconds interval then keep that for 3 minutes
than close them. Air freshening done.
A display is also necessary to set things and inform us. The 1,3"
OLED was the simplest and best for this project. Uses 3.3V and I2C.
Piece of cake.
Keypad was a hard choice. Tried several types but MPR121 Capacitive
keypad won. The 4x4 membrane also in duty elsewhere but uses 8
input. (to achive only 2 wires using different resistors connected to its'
wires gave hectic readings, so in the end membrane OK but not with 8
outputs). So the cap. keypad... Farming is a dirty thing, much have
rough hands and fingers, not to mention gloves. I have to get used to
that capacitive keypad requires clean hand.
There are dedicated switches and a button in duty. Main switch is a full
ON/OFF switch for AC 230V input. The metal tactile button only
switches the Relay coil ON/OFF (good when debugging needed). And
there is a momentary button also. Pushing it the display activates for
certain seconds and then deactivates (or pushing it again also
deactivates it). OLED displays have limited lifetime that's the reason I
put it there.
MCU cannot capable of running parallel processes at the exact same
time. To show user what is going on inside the Cube I also installed
an RGB 5MM (common cathode) LED. You can program which colour
what means in the program loop. For example in normal 'stand-by'
mode when MCU only reads sensors a blinking green colour indicates
everything is fine "you can go to your work". If freezing hits (not
happened since OLED displays used) blinking stops or it is just light
but not blinks.
The first and most important input is coming from the temperature
sensor. I chose the 1-Wire bus type DS18B20 sensor. Simple and long
range. Range is needed here, we are talking about 200 meters where
can be so much differences between temperatures. I managed to reach
50 meters using CAT5 cable. Sometimes, thanks to the EMI sensor
gives 'error' values but you can filter them easily in the software.

Ready to assembly
In the future under new project names but based on this very first
Climate Cube project i am going to install more sensors (RH%, LUX,
etc.). Optimum relative humidity for sweet pepper is important
and Si7021 sensor can measure it quite well. The amount of radiation is
also very important to know. If it is less than the optimum you have to
keep cooler temperature inside, not to turn the growing process into
vegetative stage etc.
The 'What if...' session
There are many dilemmas and 'what if...' type questions but the main
thing is we all exposed to the changes of weather. All we can do is to
adapt our micro-climate to it. First of all, for optimum adaptation we
need exact data (°C of Air, °C of Soil, RH%, Soil moisture, Watts/m2°
etc.) from our surroundings. Second, we should know what plants exact
need in certain period of production. Only after these information we
can start to think about what type of intervention should we take.
Next levels of Climate Cube
I am about to build a 3G based Wi-Fi network in the area, after that i
can monitor, manage etc. the already installed units. I real IoT based
plant production come alive soon.

SCHEMATICS
CODE
#include <HCMatrixKeypad.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Metro.h>
#include <Wire.h>
#include <Arduino.h>
#include <U8g2lib.h>
#include "RTClib.h"

#define Addrsi 0x40 //Si7021


#define Addrbh 0x23 // BH1750

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/


U8X8_PIN_NONE);

#define relayPin0 16 // a 8es kimenetre rakotve az 1 es rele ami a Zaras


#define relayPin1 17 // a 9as kimenetre rakotve a 2 es rele ami a Nyitas

#define HOMERO 0 // A homero bedugva az mcu 2es digitalis bemenetere es elnevezve


HOMEROnek

#define LED 19

/*unsigned long myChannelNumber = 258360;


const char * myWriteAPIKey = "I44H7MK2AYDPZBIJ";
const long ThingspeakDelay = 30000;*/

int kivantHomerseklet = 1800;


int homDiff = 50;

/* --------- METRO time constants ----------------- */


const int idoNyit = 700;
const int idoZar = 500;

const long varNyit= 90000;


const long varZar= 60000;
const int varLed = 700; //3600000=1 ra
const int varHumHomBes = 1923; //3600000=1 ra
const int varBeSug = 571;
const int varLcd = 1000;

/*----------------Keypad-----------------*/

#define DEBOUNCE 100 //100

#define C1 1 // DIO for keypad column 1


#define C2 2 // DIO for keypad column 2
#define C3 3 // DIO for keypad column 3
#define C4 4 // DIO for keypad column 4

#define R1 8 // DIO for keypad row 1


#define R2 7 // DIO for keypad row 2
#define R3 6 // DIO for keypad row 3
#define R4 5 // DIO for keypad row 4

HCMatrixKeypad Keypad(DEBOUNCE, C1, C2, C3, C4, ROWMARKER, R1, R2, R3,
R4);

/*1=14 . . A=11
4=24 . . B=21
7=34
*=44
*/
/*---------------------------------------------------------------------*/

int state0 = HIGH;


int state1 = HIGH;
int ledstate = LOW;

int inPin = 19; // the number of the input pin

int state = LOW; // the current state of the output pin


int previous = HIGH; // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers

int reading; // the current reading from the input pin


const int numReadings = 10;

int readings[numReadings]; // the readings from the analog input


int readIndex = 0; // the index of the current reading
int total = 0; // the running total
int tempCaverage = 0; // the average

OneWire oneWire(HOMERO); // A homero egykabeles onewire bekotest kapott


DallasTemperature sensors(&oneWire); // megadtuk a homero gyartasi tipusat es
hivatkozunk ra

RTC_DS3231 rtc;

Metro metro0 = Metro(varZar);


Metro metro1 = Metro(varNyit);
Metro ledMetro = Metro(varLed);
Metro metro3 = Metro(varHumHomBes);
Metro metro4 = Metro(varBeSug);
Metro metro5 = Metro(varLcd);
Metro rtcMetro = Metro(1000);
//Metro metro6 = Metro(ThingspeakDelay);

void setup()
{

// Initialise I2C communication as MASTER


//Wire.begin();
u8g2.begin();
Wire.setClock(32000L); //The slowest i2c speed for Mkr1000

// Initialise serial communication, set baud rate = 9600


//Serial.begin(9600);
//u8g2.setFlipMode(1);
u8g2.clearBuffer(); // clear the internal memory
u8g2.setFont(u8g2_font_7x14_tf); // choose a suitable font
u8g2.drawStr(43,10,"PaMon!"); // write something to the internal memory
u8g2.sendBuffer(); // transfer internal memory to the display
delay(2000);
u8g2.clearDisplay();

//Start I2C transmission


Wire.beginTransmission(Addrsi);

// Stop I2C transmission


Wire.endTransmission();
delay(300);

// Start I2C Transmission


Wire.beginTransmission(Addrbh);
// Send power on command
Wire.write(0x01);
// Stop I2C Transmission
Wire.endTransmission();
delay(300);

// Start I2C Transmission


Wire.beginTransmission(Addrbh);
// Send continuous -......-low precision measurement command: 0x13
Wire.write(0x10); //0x10- high-continuous measurement;0x11 high0.5 lx cont mode
120ms time
// Stop I2C Transmission
Wire.endTransmission();
delay(300);

pinMode(LED,OUTPUT);
digitalWrite(LED,ledstate);

rtc.begin();
sensors.begin(); // Elindul a homero
sensors.setResolution(10);

pinMode(relayPin0, OUTPUT);
digitalWrite(relayPin0, HIGH);

pinMode(relayPin1, OUTPUT);
digitalWrite(relayPin1, HIGH);
// initialize the button pin as a input:
pinMode(inPin, INPUT);

// initialize the LED as an output:

u8g2.clearBuffer(); // clear the internal memory


// write something to the internal memory
//u8g2.sendBuffer();

/*u8g2.setCursor(16,2);
u8g2.print("W/m2");

u8g2.setCursor(0,1);
u8g2.print("Par:");
u8g2.setCursor(8,1);
u8g2.print("%");

u8g2.setCursor(10,1);
u8g2.print("Hom:");

u8g2.setCursor(0,3);
u8g2.print("Aj.Hom:");

/*t = rtc.getTime();

if(t.hour<10) {
u8g2.setCursor(5,3);
u8g2.print("0");
u8g2.setCursor(6,3);
u8g2.print(t.hour);
}
else {
u8g2.setCursor(5,3);
u8g2.print(t.hour);
}
if(t.min<10) {
u8g2.setCursor(8,3);
u8g2.print("0");
u8g2.setCursor(9,3);
u8g2.print(t.min);
}
else {
u8g2.setCursor(8,3);
u8g2.print(t.min);
}*/

for (int thisReading = 0; thisReading < numReadings; thisReading++) {


readings[thisReading] = 0;
}

sensors.requestTemperatures();

delay(500);
metro0.reset();
metro1.reset();
ledMetro.reset();
metro3.reset();
metro4.reset();
metro5.reset();

//WiFi.begin(ssid, pass);
//ThingSpeak.begin(client);
//delay(2000);
}

void loop()
{

//

if (state0 == HIGH && state1 == HIGH) {

if (ledMetro.check() == 1) { // check if the metro has passed its interval .


if (ledstate==HIGH) ledstate=LOW;
else ledstate=HIGH;

digitalWrite(LED,ledstate);
}
float tempRaw = sensors.getTempCByIndex(0);
float tempFloat = tempRaw*100;
int tempInt = tempFloat;

// subtract the last reading:


total = total - readings[readIndex];
// read from the sensor:
if(tempInt>0 && tempInt<8000){
int tempC = tempInt;
readings[readIndex] = tempC;
//Serial.println(tempC);
}
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;

// if we're at the end of the array...


if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}

// calculate the average:


tempCaverage = total / numReadings;
// send it to the computer as ASCII digits
//Serial.println(tempCaverage);
//delay(100);

//Serial.println(sensors.getTempCByIndex(0));
//Serial.println(tempInt);

//Serial.println(tempCaverage);

u8g2.setCursor(0,10);
u8g2.print("Bh:");

u8g2.setCursor(0,24);
u8g2.print("D:");

u8g2.setCursor(0,38);
u8g2.print("Ah:");

u8g2.setCursor(0,52);
u8g2.print("Ido:");
Keypad.Scan();

/* If so the send the key to the serial port


//Serial.print("Number of Key Pressed: ");
//Serial.println(Keypad.Read());
if (Keypad.Read() > 0){
u8g2.setCursor(120,52);
u8g2.print("*");
}
else {
u8g2.setCursor(120,52);
u8g2.print(" ");
}*/

if (Keypad.Read() == 14) {
kivantHomerseklet+=100;
if (kivantHomerseklet == 2600){
kivantHomerseklet = 1600;
}

}
if (Keypad.Read() == 24) {
kivantHomerseklet-=100;
if (kivantHomerseklet == 1500){
kivantHomerseklet = 2500;
}
}

if (Keypad.Read() == 13) {

homDiff+=10;
if (homDiff > 205){
homDiff = 10;
}

}
if (Keypad.Read() == 23) {
homDiff-=10;
if (homDiff < 5){
homDiff = 200;
}
}
if (rtcMetro.check()== 1) {

DateTime now = rtc.now();

Serial.print(now.year());
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');

Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();

u8g2.setCursor(30,52);
u8g2.print(now.hour());

u8g2.setCursor(45,52);
u8g2.print(":");

u8g2.setCursor(54,52);
u8g2.print(now.minute());

int Bh = kivantHomerseklet/100;
u8g2.setCursor(23,10);
u8g2.print(Bh);

if (homDiff > 5 && homDiff < 100) {


u8g2.setCursor(18,24);
u8g2.print("0.");
u8g2.setCursor(34,24);
u8g2.print(homDiff/10);
u8g2.setCursor(42,24);
u8g2.print(" ");
}

if (homDiff > 95 && homDiff < 200) {


u8g2.setCursor(18,24);
u8g2.print(homDiff);
u8g2.setCursor(26,24);
u8g2.print(".");
u8g2.setCursor(34,24);
u8g2.print(homDiff-100);
u8g2.setCursor(42,24);
u8g2.print(" ");
}
if (homDiff==200) {
u8g2.setCursor(18,24);
u8g2.print(homDiff);
u8g2.setCursor(26,24);
u8g2.print(".");
u8g2.setCursor(34,24);
u8g2.print(homDiff-200);
u8g2.setCursor(42,24);
u8g2.print(" ");
}

u8g2.setCursor(23,38);
u8g2.print(tempRaw,1);
u8g2.setCursor(62,38);
u8g2.print("C");

//Serial.print("Jelenlegi homerseklet: ");


//Serial.println(sensors.getTempCByIndex(0)); // kiirjuk a monitorra a kapott
homersekletet

if (metro3.check()== 1 && state0 == HIGH && state1 == HIGH) {

unsigned int datasi[2];

// Start I2C transmission


Wire.beginTransmission(Addrsi);
// Send humidity measurement command, NO HOLD MASTER
Wire.write(0xF5);
// Stop I2C transmission
Wire.endTransmission();
delay(150);

// Request 2 bytes of data


Wire.requestFrom(Addrsi, 2);

// Read 2 bytes of data


// humidity msb, humidity lsb
if(Wire.available() == 2)
{
datasi[0] = Wire.read();
datasi[1] = Wire.read();
}

// Convert the data


float humidity = ((datasi[0] * 256.0) + datasi[1]);
humidity = ((125 * humidity) / 65536.0) - 6;

// Start I2C transmission


Wire.beginTransmission(Addrsi);
// Send temperature measurement command, NO HOLD MASTER
Wire.write(0xF3);
// Stop I2C transmission
Wire.endTransmission();
delay(150);

// Request 2 bytes of data


Wire.requestFrom(Addrsi, 2);

// Read 2 bytes of data


// temp msb, temp lsb
if(Wire.available() == 2)
{
datasi[0] = Wire.read();
datasi[1] = Wire.read();
}

// Convert the data


float temp = ((datasi[0] * 256.00) + datasi[1]);
float cTemp = ((175.72 * temp) / 65536.00) - 46.85;

unsigned int databh[2];


// Request 2 byte of data
Wire.requestFrom(Addrbh, 2);
// Read 2 bytes of data
// ALS msb, ALS lsb
if(Wire.available() == 2)
{
databh[0] = Wire.read();
databh[1] = Wire.read();
}
//delay(130);

//convert the data


float luxraw = (((databh[0] * 256.0000) + databh[1]) / 1.2000);
float irradiation = (((databh[0] * 256.0000) + databh[1]) / 1.2000)*0.0079;
int lux = irradiation;

/*if(humidity<=0) {
u8g2.setCursor(4,1);
u8g2.print(" 0 ");

}
if(humidity>0 && humidity<100) {
u8g2.setCursor(4,1);
u8g2.print(humidity,0);
u8g2.setCursor(6,1);
u8g2.print(" ");
}
if(humidity>=100 && humidity<=115) {
u8g2.setCursor(4,1);
u8g2.print(humidity,0);
u8g2.setCursor(7,1);
u8g2.print(" ");
}
if(humidity>115) {
u8g2.setCursor(5,1);
u8g2.print("115");
u8g2.setCursor(4,1);
u8g2.print(">");
}

u8g2.setCursor(14,1);
u8g2.print(cTemp, 1);
u8g2.setCursor(19,1);
u8g2.print("C");
if(lux<10) {
u8g2.setCursor(12,2);
u8g2.print(lux);
u8g2.setCursor(13,2);
u8g2.print(" ");
u8g2.setCursor(14,2);
u8g2.print(" ");

if(lux>=10 && lux<100) {


u8g2.setCursor(12,2);
u8g2.print(lux);
u8g2.setCursor(14,2);
u8g2.print(" ");

if(lux>=100 && lux<1000) {


u8g2.setCursor(12,2);
u8g2.print(lux);

if(lux>1000) {
u8g2.setCursor(11,2);
u8g2.print(lux);

if(lux<100) {
u8g2.setCursor(7,3);
u8g2.print("18-20 ");
u8g2.setCursor(13,3);
u8g2.print("C");
}

if(lux>=100 && lux<200){


u8g2.setCursor(7,3);
u8g2.print("21-22 ");
u8g2.setCursor(13,3);
u8g2.print("C");
}
if(lux>=200 && lux<300) {
u8g2.setCursor(7,3);
u8g2.print("23-24 ");
u8g2.setCursor(13,3);
u8g2.print("C");
}

if(lux>=300 && lux<400) {


u8g2.setCursor(7,3);
u8g2.print("25-26 ");
u8g2.setCursor(13,3);
u8g2.print("C");
}
if(lux>=400) {
u8g2.setCursor(7,3);
u8g2.print("Arnyek");
u8g2.setCursor(13,3);
u8g2.print(" ");
}*/

// Output data to serial monitor


Serial.print("Ambient Light Luminance :");
Serial.print(irradiation);
Serial.println(" lux");

// Output data to serial monitor


Serial.print("Relative humidity : ");
Serial.print(humidity);
Serial.println(" % RH");
Serial.print("Temperature in Celsius : ");
Serial.print(cTemp);
Serial.println(" C");
Serial.print("LUX: ");
Serial.print(luxraw);
Serial.println(" lx");

//u8g2.setCursor(0,2);
//u8g2.print("Besugarzas:");

}
reading = digitalRead(inPin);

// if the input just went from LOW and HIGH and we've waited long enough
// to ignore any noise on the circuit, toggle the output pin and remember
// the time
if (reading == HIGH && previous == LOW) {
if (state == HIGH)
state = LOW;
else
state = HIGH;
metro5.reset();
}

if (state == HIGH) {
u8g2.sendBuffer();
Serial.println("OLED ON");
metro5.interval(20000);
}

if(metro5.check() == 1 && state == HIGH){


state = LOW;
}

if (state == LOW) {
// if the current state is LOW then the button
// wend from on to off:
u8g2.clearDisplay();
}
previous = reading;

} // closes the display and measuring methods

if ((kivantHomerseklet-homDiff) == tempCaverage ) {
digitalWrite(relayPin0, HIGH);
digitalWrite(relayPin1, HIGH);
}
if ((kivantHomerseklet+homDiff) == tempCaverage) {
digitalWrite(relayPin0, HIGH);
digitalWrite(relayPin1, HIGH);
}
if (((kivantHomerseklet-homDiff) < tempCaverage && tempCaverage <
(kivantHomerseklet+homDiff)) && relayPin0==LOW) {
digitalWrite(relayPin0, HIGH);
}
if (((kivantHomerseklet-homDiff) < tempCaverage && tempCaverage <
(kivantHomerseklet+homDiff)) && relayPin1==LOW) {
digitalWrite(relayPin1, HIGH);
}

if ((tempCaverage < (kivantHomerseklet-homDiff)) && relayPin1==LOW) {


digitalWrite(relayPin1, HIGH);
}

if ((tempCaverage > (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

× 1

USB A-B Cable


× 1

5V 1.2A AC-to-DC Adapter


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

Driver PCB based on ULN2003A


It is useful for driving unipolar 4
×
stepper motors. Works like digital
amplifier.
M6 Coupling Nut 10 mm Long
Needed to fix rod with motor's × 4
shaft.
M6 Threaded Rod
× 1
1 meter is just fine.
Universal breadboard SYB-46
× 1
Solderless technologies!
20cm Male-to-Male Jumper Wire
Cable 2.54mm × 20

20cm Male-to-Female Jumper Wire


Cable 2.54mm × 40
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 G-
code.

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 A-
AB-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 H-
bridge 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 high-
current 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 <AccelStepper.h>
#include <MultiStepper.h>

#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

× 1

Ultrasonic Sensor - HC-SR04 (Generic)


× 1

Recycled vibrator motor of cell phone


× 1

Recycled cables
× 1

5v Rechargable battery of 2000mAh.


× 1
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){
Serial.println("____");
}
else{
Serial.print(distance);
Serial.println("cm.");
digitalWrite(5,LOW);
}
if(distance<=45 && distance>=1){// distance in which the bracelet vibrates, you can edit
according to your need

digitalWrite(5,HIGH);
Serial.println("Alarm!!!");
}
delay(400);
}

55) IoT Arduino Ball Tracking


COMPONENTS AND SUPPLIES
Arduino Micro & Genuino Micro

× 1

Servos (Tower Pro MG996R)


× 1

Android device

× 1

SparkFun WiFi Breakout -


CC3000 × 1
APPS AND ONLINE SERVICES
IoT Colored Ball Tracker

IoT WiFi | Bluetooth Rounded Objects


Tracking

ABOUT THIS PROJECT

The advancement and development of high resolution per frame cameras


in recent years motivate both engineers and students in the research and
creation of applications based on "automated" computer vision algorithms,
a frequent task and used for the tracking of object movements and position
of the object, as well as its own characteristics, such as object shape,
object color, etc.
In this case, the project is based on the tracking of moving objects and
specific characteristics of these, such as circular or spherical shapes and
color, besides positioning and movement of these.
The colors that can be detected with this application are:
Red
Orange
Yellow
Green
Blue
Violet
But tracking is not limited just to this type of tracking, also you can track
recognition of the face, eyes, body parts such as hands, arms, legs, head,
etc.
Some areas in which object tracking can be applied are:
Bodies in motion
Vigilance
Recognition of facial gestures
Body movements
Automated navigation
Trajectories performed by objects.
As I mentioned above the tracking is made on circular colored objects.
With regard to the hardware, I do not have enough elements to make a
robotic arm of at least two servos. I only have one and a smartphone
camera a little outdated with Android operating system.
How does it work:
Run the application. Select WiFi in the menu to register the target host and
port by which the information will be sent to the WiFi module. And your
Arduino can receive the information and can make the necessary
calculations.
Then you can select the color to be tracked or from the menu select Ball,
and begin to track. When it detects the object of the selected color, the
application will begin sending the necessary data.
Arduino Micro receives information about the object through a WiFi
module, in this case the SparkFun Breakout Board CC3000 from IT. The
communication is done through UDP sockets client server, the application
in the mobile sends the necessary data (frame size position for horizontal
and vertical servo) to the microcontroller, so that this can perform the
calculations with the information sent and perform the updates in the
servos, in this case only the horizontal.

SCHEMATICS
CODE
#include <avr/delay.h>

/* servo libs */
#include "_Servo.h"

/* WiFi libs */
#include "CC3000.h"
#include "CC3000_Client.h"
#include "common.h"

Servo servo_x;
Servo servo_y;

void setup()
{
/* add setup code here */
ConnectionInfo connection_info;

// Initialize CC3000 (configure SPI communications)


#ifdef CC3000_DEBUG
Serial.begin(115200);
#endif

// Initialize CC3000 (configure SPI communications)


if(!wifi.init(9)) {
#ifdef CC3000_DEBUG
DEBUGPRINTLN(PSTR("Initialize CC3000 FAIL!"));
#endif
return;
}

else {
//FreeRam();
#ifdef CC3000_DEBUG
DEBUGPRINTLN(PSTR("Initialize CC3000 OK"));
#endif
}

if(!wifi.connect(ap_ssid, ap_security, ap_password, timeout))


{
#ifdef CC3000_DEBUG
DEBUGPRINTLN(PSTR("Error: Could not connect to AP!"));
#endif
}

// Gather connection details and print IP address


if(!wifi.getConnectionInfo(connection_info) )
{
#ifdef CC3000_DEBUG
DEBUGPRINTLN(PSTR("Error: Could not obtain connection details"));
#endif
return;
}

else
{
#ifdef CC3000_DEBUG
DEBUGPRINT(PSTR("IP Address: "));
printIPAddr(connection_info.ip_address);
#endif
}

pin_mode(SERVO_PIN_X, OUTPUT); // declare the LED's pin as output


pin_mode(SERVO_PIN_Y, OUTPUT); // declare the LED's pin as output

servo_x.attach(SERVO_PIN_X);
servo_y.attach(SERVO_PIN_Y);

// center servos
servo_x.write(SERVO_CENTER_X);
servo_y.write(SERVO_CENTER_Y);

_delay_ms(200);
}

void loop()
{

}
56) Arduino Event Monitor for Independent Senior Citizens

COMPONENTS AND SUPPLIES

Arduino MKR1000

× 1

ADXL345
× 1
DS18B20
× 1

Photo resistor

× 1

3 mm LED: Red

× 1

3 mm LED: Green

× 1

Buzzer

× 1

Resistor 4.75k ohm

× 3

Resistor 1k ohm

× 2

Resistor 10k ohm

× 1
Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Li-Ion Battery 100mAh

× 1

ABOUT THIS PROJECT

The aging population of the world presents enormous financial challenges.


There are not enough retirement facilities to cater the needs of the elderly
and costs are high. The tendency is that elderly people prefer staying in
their own homes for longer. That makes the elderly more independent and
happier, but risks are higher when they fall or experience health or
security problems. Sometimes that is only discovered hours or days after
the incident.
With this non-invasive system daily events can be monitored and recorded
and a set of rules can be applied to generate an alarm condition. This
includes:
opening and closing doors
switching lights on or off
using electrical appliances
movement in various locations in the house
temperature measurement
panic button
fall detection (monitor worn by elderly)
A summary of this information will be sent to the cloud. With the monitor
app users with access to the service will be able to monitor various
statuses and will be alerted of emergency situations. These users may
include family, friends, emergency services and health services.

Infrastructure Needed to Provide the Service:


one or more wifi sensor nodes to collect relevant data
wifi network infrastructure
data cloud storage and service infrastructure
client app to display cloud collected data and control sensor nodes via
the cloud
A number of different sensors are used to accumulate data for a rules
based system, which will send alerts when events do not follow a normal
pattern. These include, but are not restricted to:
a) accelerometer - vibration (eg. fridge running), orientation or fall
detection (where the device is worn by the person), objects being
moved (sensor device attached to the object)
b) light sensor - to determine whether lights are on and/or sun is shining
(curtains drawn of not)
c) temperature - to measure room temperature (too hot or too cold)
d) magnetic switch OR motion monitor contact - to determine when a
door is opened or closed (when not supposed to) OR lack thereof
(which may be an abnormal condition) OR lack of motion (for a period
of time in a specific time slot)
All these events are time stamped, so that rules can include time of day,
time slots and time span.
A bi-color LED and buzzer is used to communicate remote messages and
as local alarm when the internet is not available. Messages may include
reminders like medication, time to feed the cat, time for a meal, etc.
The assumption is that a wifi router, which is connected to the internet,
will be available. The wifi sensor node makes use of DHCP to obtain an
IP address.
Cloud Environment
The wifi sensor node currently makes use of a free subscription to the
Microsoft Azure IoT Hub to store data. Setup and tools will be described
in the software section.
As a proof of concept I used the Azure Device Monitor software to analyze
data and to send commands to my MKR1000 sensor node via Azure IoT
Hub.
I also installed the Azure IoT Suite and had a look at their example
application (more under software).
In future a Windows 10 app will be used to display data (light level,
temperature) and alerts (fall, door open) from Azure IoT Hub and to send
signal commands to wifi sensor nodes via the hub.
Hardware Setup
Initially I did my prototype on a breadboard, as shown in the first picture.
The second picture shows the schematic. Towards the end I decided to do
a more permanent setup for testing and I built the circuit on prototype
board, as seen in the project picture. The Fritzing file is available under
uploaded files.

MKR1000 Sensor Node Breadboard


MKR1000 Sensor node Schematic

Upgrade to MKR1000 core version 1.6.4-mkr02, which contains a crucial


fix for a condition that destroys the bootloader. Install the latest Arduino
Wifi101 library.
Setup the Arduino IDE for MKR1000, plug the module into a usb port and
ensure that the correct serial port is selected. There are good example
sketches in Wifi101 to turn the module into a webclient or webserver. Try
these out to ensure that your board is working properly.
Change ssid and pass to connect to your own wifi router.
Refer to the hardware schematics and component list to prepare the wifi
sensor node. The pinouts are well documented in the Arduino sketch.
Initially I planned on using Windows Remote Arduino, which is a
Windows 10 environment that uses firmata protocol to "take over" the
Arduino. This would poll remote sensors from a Windows app. Due to the
unpredictable nature of accelerometer data I decided against this method,
in favor of pushing sensor data to the cloud. The obvious choice
was Microsoft Azure IoT Hub.
MKR1000 Sensor Node Sketch
I am thrilled to be in the group of 1000 to familiarize myself with the
MKR1000. Initially I worked through example sketches in the Wifi101
library. After I defined the goal of my project I made a decision on the
sensors and other components I would use, preferably in stock items. I
collected libraries and examples for LDR light dependent resistor,
DS18B20 temperature sensor, ADXL345 accelerometer, switch, bi-color
LED, buzzer and tested them individually on a breadboard. I had to
quickly learn Fritzing to do the schematic and breadboard layout (see
hardware setup).
I received lots of help from members on the MKR1000 forum, as well as
other hobbyists (see references). At this stage I had only heard about
Azure, but I decided to use it for cloud data storage anyway. The vast
capabilities of the Azure cloud platform was quite confusing. Fortunately
Mohan Palanisami (mohanp) did a good article on connecting to Azure
IoT Hub. A "simple C" sample on azure-iot-sdks looked promising, but it
was not that simple after all and I did not like the 100k+ size of my sketch.
I noticed that mohanp only used around 30k, so I decided to use his sketch
as basis. Initially I used the JSON structure in the connect the dots library
examples, but now I am using a very neat JSON library for generating
strings.
In the main loop there are basic local rules for determining an event
condition (temperature changing x degrees, light level changing y lumens,
accelerometer events, battery voltage falling under 3.3V). When an event
occurs the data gets sent to Azure IoT Hub, where a secondary set of rules
is applied on the data to decide on an alarm condition (abnormal events in
specific time slots or time spans). Currently this is not implemented, but
the Azure IoT Suite example shows how it can be done.
Further work needs to be done to decode combinations of accelerometer
"words" (INACTIVITY, ACTIVITY, TAP, DOUBLE TAP, FALL
DETECT) into real life events (like fall, object moved, vibration stopped).
With the extension of the deadline I managed to add more functionality:
JSON generation is simplified by using JSON library calls. The JSON
string is also simplified.
Commands received from Azure IoT Hub via the Device
Explorer "messages to device" tab are executed on the MKR1000.
Examples are beepon/beepoff to turn the buzzer on of off. Similarly
this could in future be used to turn a relay on/off to control electrical
devices.
I moved from the Arduino IDE environment to Visual
Studio with Visual Micro, Azure IoT Hub and Github extensions. I
posted my local library to Github from here.
Azure Hub Setup
If you are not already using Azure you can subscribe to a free account.
Use the Azure portal to create you own IoT Hub (mine is
called MKR1000hub)
https://azure.microsoft.com/en-in/documentation/articles/iot-hub-csharp-
csharp-getstarted/.
To enable you to create and explore devices on Azure install Device
Explorer for IoT Hub devices
https://github.com/Azure/azure-iot-
sdks/blob/master/tools/DeviceExplorer/doc/how_to_use_device_explorer.md
Configure the Device Explorer by using the IoT Hub Connection String
and Protocol Gateway Hostname from Azure portal. Go to the
Management tab to create a device. Use this connection string in the
MKR1000 sensor node sketch. The Data tab enables you to display the
JSON messages sent to Azure. The Messages to Device tab enable you to
send messages to the MKR1000 sensor node (as described in the sketch
section).

Azure IoT Suite


An excellent example application monitors and displays temperature and
humidity. That together with the ease of registering new devices and the
rules engine makes it ideal for my project. I adapted my sketch to send
data to the sample Azure IoT Hub, which according to Device Explorer
worked. The device showed up in the IoT Device Portal, but the status
stayed "pending". More people complained about getting the same results
sending from Arduino, but could not get any clarity on solving the
problem. I could also not find documentation on the JSON schema they
use. I tried to reverse engineer it by looking at the sample data in Device
Explorer, but I may still be missing something.

SCHEMATICS
CODE
MKR1000 Azure Sensor Node Sketch

/* MKR1000Azure.ino - MKR1000 Azure IoT HTTP client with sensors


sending data to Azure IoT Suit example

Tested joepvanwyk 11 Mar 2016 - adapted from MKRAzure.ino written


by Mohan Palanisamy (http://mohanp.com)
Instructions are here to properly set up the MKR1000 for SSL connections
http://mohanp.com/mkr1000-azure-iot-hub-how-to/

Additional code used from sample sketches:


------------------------------------------
Connectthedots - DS18B20.ino // temperature sensor code outputs
degrees Centigrade
Bildr - ADXL345_Example.ino // ADXL345 accelerometer
statuses INACTIVITY, ACTIVITY, FALL DETECT, TAP, DOUBLE
TAP
Github - JsonGeneratorExample.ino // Benoit Blanchon's Json
library example simplifies JSON generation parts of mohanp's code

MKR1000 pinouts:
----------------
LDR analog A0 2
Battery voltage A1 3
LED red D0 9
LED green D1 10
DS18B20 signal D2 11
ADXL345 INT1 ?
Buzzer D3 12
Switch D4 13
MKR1000_LED D6 15 // internal LED
ADXL345 SDA D11 21
ADXL345 SCL D12 22

GND 25
Vcc 26
Vin 27

Rules for posting data to Azure:


--------------------------------
1. Temperature changes by more than 0.5 degrees C
2. Accelerometer combination of statuses defines action
3. Light level changes by more than 100 units
4. Battery voltage falls below 3.3V
5. Switch status changes (door open or close)

Copyright (c) Arduino. All rights reserved.


Licensed under the MIT license. See LICENSE file in the project root for
full license information.

*/

#include <SPI.h>
#include <WiFi101.h>
#include <Wire.h>
#include <ADXL345.h>
#include <OneWire.h>
#include <avr/dtostrf.h>
#include <ArduinoJson.h>

// WiFi Network Config


char ssid[] = "wlan-ap"; // your network SSID (name)
char pass[] = "qwerty123"; // your network password (use for WPA,
or use as key for WEP)
// Device Explorer - Protocol Gateway Hostname
char hostname[] = "RethinkAzureSensorNode.azure-devices.net";
// IoT Hub Connection String:
HostName=RethinkAzureSensorNode.azure-
devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=yypCMvmAHIZ

// Device Explorer - Generated SAS


char authSAS[] = "SharedAccessSignature
sr=RethinkAzureSensorNode.azure-
devices.net&sig=g%2bQHMLYInsPrvbmyeC9QRsA6kutL8dQTpz5ruR%2b%2fiY0%

char feeduri[] = "/devices/RethinkAzureSuite01/messages/devicebound?


api-version=2016-02-03"; // feed URI
char azurePOST_Uri[] =
"/devices/RethinkAzureSuite01/messages/events?api-version=2016-02-
03"; // feed POST Uri

// message Complete/Reject/Abandon URIs. "etag" will be replaced with


the message id E-Tag recieved from recieve call.
String azureComplete =
"/devices/RethinkAzureSuite01/messages/devicebound/etag?api-
version=2016-02-03";
String azureReject =
"/devices/RethinkAzureSuite01/messages/devicebound/etag?reject&api-
version=2016-02-03";
String azureAbandon =
"/devices/RethinkAzureSuite01/messages/devicebound/etag/abandon?
&api-version=2016-02-03";

char DeviceID[] = "RethinkAzureSuite01";


char buffer[256]; // JSON data buffer

// Sensor stuff
#define ldrPin A0 // light sensor
#define batPin A1 // battery voltage
#define LED_red 0 // red status led
#define LED_green 1 // green status led
#define DS18S20_Pin 2 // DS18S20 Signal pin
#define Buzzer 3 // sound output
#define swPin 4 // switch input
#define MKR1000_LED 6 // internal LED

float prevtemp = 0;
float prevacc = 0;
float prevlight = 0;
float prevbattery = 0;
int prevswitch = 0;

unsigned long time_last = millis();


unsigned long time_new = millis();
int polltime = 5; // minimum time between sending to Azure

int status = WL_IDLE_STATUS;

OneWire ds(DS18S20_Pin); // instantiate temperature object


ADXL345 adxl; // variable adxl is an instance of the ADXL345
library
WiFiSSLClient client; // instantiate wifi object
void setup()
{

/* serial is for debugging */


Serial.begin(9600);
int i;
while (!Serial) { if (i++ >= 512) break; } // wait for serial to
connect

// setup I/Os
pinMode(LED_red, OUTPUT); // status LED red
digitalWrite(LED_red, HIGH); // high is off
pinMode(LED_green, OUTPUT); // status LED green
digitalWrite(LED_green, HIGH); // high is off
pinMode(Buzzer, OUTPUT); // sound out
digitalWrite(Buzzer, LOW); // low is off
pinMode(MKR1000_LED, OUTPUT); // internal LED
pinMode(swPin, INPUT); // external switch

// ADXL345 accelerometer setup


adxl.powerOn();
//set activity/ inactivity thresholds (0-255)
adxl.setActivityThreshold(75); //62.5mg per increment
adxl.setInactivityThreshold(75); //62.5mg per increment
adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
//look of activity movement on this axes - 1 == on; 0 == off
adxl.setActivityX(1);
adxl.setActivityY(1);
adxl.setActivityZ(1);
//look of inactivity movement on this axes - 1 == on; 0 == off
adxl.setInactivityX(1);
adxl.setInactivityY(1);
adxl.setInactivityZ(1);
//look of tap movement on this axes - 1 == on; 0 == off
adxl.setTapDetectionOnX(0);
adxl.setTapDetectionOnY(0);
adxl.setTapDetectionOnZ(1);
//set values for what is a tap, and what is a double tap (0-255)
adxl.setTapThreshold(50); //62.5mg per increment
adxl.setTapDuration(15); //625s per increment
adxl.setDoubleTapLatency(80); //1.25ms per increment
adxl.setDoubleTapWindow(200); //1.25ms per increment
//set values for what is considered freefall (0-255)
adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per
increment
adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per
increment
//setting all interupts to take place on int pin 1
//I had issues with int pin 2, was unable to reset it
adxl.setInterruptMapping(ADXL345_INT_SINGLE_TAP_BIT,
ADXL345_INT1_PIN);
adxl.setInterruptMapping(ADXL345_INT_DOUBLE_TAP_BIT,
ADXL345_INT1_PIN);
adxl.setInterruptMapping(ADXL345_INT_FREE_FALL_BIT,
ADXL345_INT1_PIN);
adxl.setInterruptMapping(ADXL345_INT_ACTIVITY_BIT,
ADXL345_INT1_PIN);
adxl.setInterruptMapping(ADXL345_INT_INACTIVITY_BIT,
ADXL345_INT1_PIN);
//register interupt actions - 1 == on; 0 == off
adxl.setInterrupt(ADXL345_INT_SINGLE_TAP_BIT, 1);
adxl.setInterrupt(ADXL345_INT_DOUBLE_TAP_BIT, 1);
adxl.setInterrupt(ADXL345_INT_FREE_FALL_BIT, 1);
adxl.setInterrupt(ADXL345_INT_ACTIVITY_BIT, 1);
adxl.setInterrupt(ADXL345_INT_INACTIVITY_BIT, 1);

//check for the presence of the shield:


if (WiFi.status() == WL_NO_SHIELD) {
// don't continue:
while (true);
}

// attempt to connect to Wifi network:


while (status != WL_CONNECTED) {
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
}

void loop()
{
// Check for messages from Azure IoT Hub and process them
azureHttpMessage();

// Read accelerometer and send to Azure


int acc = getAccelerometer();
if (acc > 0) { // acceleration action sensed
if (wifiConnect()) {
prevacc = acc;
LED_blink(LED_red, 50, 1);
httpRequest("POST", azurePOST_Uri, "", buffer); // buffer contains
JSON data
delay(polltime);
}
}

// Read temperature and send to Azure


float temp = getTemp();
float temp1 = (temp - prevtemp);
if (abs(temp1) > 1) { // temperature changed by more than 1 degrees
C
if (wifiConnect()) {
prevtemp = temp;
LED_blink(LED_red, 50, 2);
httpRequest("POST", azurePOST_Uri, "", buffer); // buffer contains
JSON data
delay(polltime); // minimum poll time in seconds
}
}

// Read lightlevel and send to Azure


float light = getLight();
float light1 = (light - prevlight);
if (abs(light1) > 100) { // light level changed more than 100 units
if (wifiConnect()) {
prevlight = light;
LED_blink(LED_red, 50, 3);
httpRequest("POST", azurePOST_Uri, "", buffer); // buffer contains
JSON data
delay(polltime); // minimum poll time in seconds
}
}

// Read battery voltage and send to Azure


float battery = getBatteryV();
float battery1 = (battery - prevbattery);
if (abs(battery1) > 100) { // battery voltage changed more than 0.5V
if (wifiConnect()) {
prevbattery = battery;
LED_blink(LED_red, 50, 4);
httpRequest("POST", azurePOST_Uri, "", buffer); // buffer contains
JSON data
delay(polltime); // minimum poll time in seconds
}
}

int switchstatus = getSwitch();


if (!(switchstatus == prevswitch)) {
if (wifiConnect()) {
prevswitch = switchstatus;
LED_blink(LED_red, 50, 5);
httpRequest("POST", azurePOST_Uri, "", buffer); // buffer contains
JSON data
delay(polltime); // minimum poll time in seconds
}
}

time_new = millis();
if ((time_new - time_last) > 20000) {
LED_blink(LED_green, 50, 2);
time_last = millis();
azureIoTReceiveMessage(); // send Azure request for message
}
}

/************ Read temperature ************/


float getTemp() {
//returns the temperature from one DS18S20 in Centigrade
byte data1[12];
byte addr[8];

if (!ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}

if (OneWire::crc8(addr, 7) != addr[7]) {
return -1000;
}

if (addr[0] == 0x10) {
//Sensor is a DS18S20
}
else if (addr[0] == 0x28) {
//Sensor is a DS18BS20
}
else
{
return -1000;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end

byte present = ds.reset();


ds.select(addr);
ds.write(0xBE); // Read Scratchpad

for (int i = 0; i < 9; i++) { // we need 9 bytes


data1[i] = ds.read();
}

ds.reset_search();

byte MSB = data1[1];


byte LSB = data1[0];

float tempRead = ((MSB << 8) | LSB); //using two's compliment


float TemperatureSum = tempRead / 16;
// JSON buffer created
// Create the root of the object tree.
StaticJsonBuffer<256> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["DeviceID"] = DeviceID;
root["Temperature"] = double_with_n_digits(TemperatureSum, 2);
// Print to buffer
root.printTo(buffer, sizeof(buffer));

return TemperatureSum;

/************ Read accelerometer ************/

int getAccelerometer() {
char action[50]; // strcat needs a character array
memset(action, '\0', sizeof(action));
int interrupt = 0;

int x, y, z;
adxl.readAccel(&x, &y, &z); //read the accelerometer values and store
them in variables x,y,z
//read interrupts source and look for triggerd actions
byte interrupts = adxl.getInterruptSource();

// freefall
if (adxl.triggered(interrupts, ADXL345_FREE_FALL)) {
strcat(action, "freefall ");
interrupt = 1;
//add code here to do when freefall is sensed
}

//inactivity
if (adxl.triggered(interrupts, ADXL345_INACTIVITY)) {
strcat(action, "inactivity ");
interrupt = 0;
//add code here to do when inactivity is sensed
}

//activity
if (adxl.triggered(interrupts, ADXL345_ACTIVITY)) {
strcat(action, "activity ");
interrupt = 1;
//add code here to do when activity is sensed
}

//double tap
if (adxl.triggered(interrupts, ADXL345_DOUBLE_TAP)) {
strcat(action, "double tap ");
interrupt = 1;
//add code here to do when a 2X tap is sensed
}

//tap
if (adxl.triggered(interrupts, ADXL345_SINGLE_TAP)) {
strcat(action, "tap ");
interrupt = 1;
//add code here to do when a tap is sensed
}
// JSON buffer created
// Create the root of the object tree.
StaticJsonBuffer<256> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["DeviceID"] = DeviceID;
root["Accelerometer"] = action;
// Print to buffer
root.printTo(buffer, sizeof(buffer));

return interrupt;
}

/************ Read lightlevel ************/

float getLight() {
float lightlevel = analogRead(ldrPin);

// Create the root of the object tree.


StaticJsonBuffer<256> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
// JSON buffer created
root["DeviceID"] = DeviceID;
root["Lightlevel"] = double_with_n_digits(lightlevel, 2);
// Print to buffer
root.printTo(buffer, sizeof(buffer));

return lightlevel;
}

/************ Read battery voltage ************/

float getBatteryV() {
float batteryV = analogRead(batPin);

// Create the root of the object tree.


StaticJsonBuffer<256> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
// JSON buffer created
root["DeviceID"] = DeviceID;
root["Batvolts"] = double_with_n_digits(batteryV, 2);
// Print to buffer
root.printTo(buffer, sizeof(buffer));

return batteryV;
}

/************ Read switch ************/

int getSwitch() {
int swStatus = digitalRead(swPin);
char truefalse[5]; // strcat needs a character array
memset(truefalse, '\0', sizeof(truefalse));

if (swStatus == 0) {
strcat(truefalse, "OFF");
}
else
{
strcat(truefalse, "ON");
}

// Create the root of the object tree.


StaticJsonBuffer<256> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
// JSON buffer created
root["DeviceID"] = DeviceID;
root["Switch"] = truefalse;
// Print to buffer
root.printTo(buffer, sizeof(buffer));

return swStatus;
}

/********************* Blink ***********************/

void LED_blink(int portnum, int timedelay, int flashnum) {


for (int i = 0; i < flashnum; i++) {
digitalWrite(portnum, LOW);
delay(timedelay);
digitalWrite(portnum, HIGH);
delay(timedelay);
}

//******************* Open WiFi connection ****************/

int wifiConnect() {
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
status = WiFi.begin(ssid, pass);
// wait 1 seconds for connection:
delay(1000);
}
return 1;
}

/**************************** Azure related methods


**************************/

/************* this method checks for messages from the Aure IoT Hub
and processes them ***************/

void azureHttpMessage() {
String response = "";
char c;
///read response if WiFi Client is available
while (client.available()) {
c = client.read();
response.concat(c);
}

if (!response.equals(""))
{
//if there are no messages in the IoT Hub Device queue, Azure will return
204 status code.
if (response.startsWith("HTTP/1.1 204"))
{
//turn off onboard LED
digitalWrite(MKR1000_LED, LOW);
}
else
{
//turn on onboard LED
digitalWrite(MKR1000_LED, HIGH);

// get the ETag from the received message response


String eTag = getHeaderValue(response, "ETag");

// get the payload from the message response


String command = getResponsePayload(response);

azureIoTCompleteMessage(eTag);
if (command == "beepon") {
//turn on buzzer
digitalWrite(Buzzer, HIGH);
}

if (command == "beepoff") {
//turn off buzzer
digitalWrite(Buzzer, LOW);
}
}
}
}

/************* Receive Azure IoT Hub "cloud-to-device" message


***************/

void azureIoTReceiveMessage()
{
httpRequest("GET", feeduri, "", "");
}

/************* Tells Azure IoT Hub that the message with the
msgLockId is handled and it can be removed from the queue
***************/

void azureIoTCompleteMessage(String eTag)


{
String uri = azureComplete;
uri.replace("etag", trimETag(eTag));

httpRequest("DELETE", uri, "", "");


}

/************* Azure POST, GET, DELETE requests


***************/

void httpRequest(String verb, String uri, String contentType, String


content)
{
if (verb.equals("")) return;
if (uri.equals("")) return;

// close any connection before send a new request.


// This will free the socket on the WiFi shield
// client.stop();

// if there's a successful connection:


if (client.connect(hostname, 443)) {
client.print(verb); //send POST, GET or DELETE
client.print(" ");
client.print(uri); // any of the URI
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(hostname); //with hostname header
client.print("Authorization: ");
client.println(authSAS); //Authorization SAS token obtained from
Azure IoT device explorer
client.println("Connection: close");

if (verb.equals("POST"))
{
client.print("Content-Type: ");
client.println(contentType);
client.print("Content-Length: ");
client.println(content.length());
client.println();
client.println(content);

}
else
{
client.println();
}
}
}

/************* To get only the message header from http response


***************/

String getHeaderValue(String response, String headerName)


{
String headerSection = getHeaderSection(response);
String headerValue = "";

int idx = headerSection.indexOf(headerName);

if (idx >= 0)
{
int skip = 0;
if (headerName.endsWith(":"))
skip = headerName.length() + 1;
else
skip = headerName.length() + 2;

int idxStart = idx + skip;


int idxEnd = headerSection.indexOf("\r\n", idxStart);
headerValue = response.substring(idxStart, idxEnd);
}

return headerValue;
}

/********** Azure IoT sets ETag string enclosed in double quotes, not in
sync with its other endpoints - need to remove the double quotes
************/

String trimETag(String value)


{
String retVal = value;

if (value.startsWith("\""))
retVal = value.substring(1);

if (value.endsWith("\""))
retVal = retVal.substring(0, retVal.length() - 1);

return retVal;
}

/************* To get all the headers from the HTTP Response


***************/

String getHeaderSection(String response)


{
int idxHdrEnd = response.indexOf("\r\n\r\n");

return response.substring(0, idxHdrEnd);


}

/************* To get only the message payload from http response


***************/

String getResponsePayload(String response)


{
int idxHdrEnd = response.indexOf("\r\n\r\n");
return response.substring(idxHdrEnd + 4);
}

Azure sensor dataPlain text

Azure JSON data as viewed in Device Explorer

Receiving events...
26 Mar 2016 10:44:14 PM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Temperature":24.44}]
27 Mar 2016 8:40:50 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Temperature":85.00}]
27 Mar 2016 8:40:50 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Temperature":18.62}]
27 Mar 2016 8:43:49 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Temperature":19.69}]
27 Mar 2016 8:49:26 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Temperature":20.75}]
27 Mar 2016 8:51:44 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":451.00}]
27 Mar 2016 9:06:44 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Temperature":21.81}]
27 Mar 2016 9:07:31 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":364.00}]
27 Mar 2016 9:11:16 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":376.00}]
27 Mar 2016 9:11:59 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":477.00}]
27 Mar 2016 9:13:11 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":335.00}]
27 Mar 2016 9:26:48 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":420.00}]
27 Mar 2016 9:27:24 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":521.00}]
27 Mar 2016 9:39:31 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Temperature":20.75}]
27 Mar 2016 9:51:58 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Lightlevel":398.00}]
27 Mar 2016 9:52:25 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Switch":"OFF"}]
27 Mar 2016 9:52:34 AM> Device: [RethinkAzureSuite01], Data:
[{"DeviceID":"RethinkAzureSuite01","Switch":"ON"}]
Commands sent from Device Explorer

Started monitoring feedback for device RethinkAzureSuite01.


Sent to Device ID: [RethinkAzureSuite01], Message:"beepon", message
Id: 737786cd-50e5-4bca-bc80-7aeddcc78466
Sent to Device ID: [RethinkAzureSuite01], Message:"beepoff", message
Id: 748fb613-8f06-4bdd-b228-256d1cfefef2
57) Arduino Washing Machine Timer

COMPONENTS AND SUPPLIES


SparkFun Arduino Pro Mini 328 -
5V/16MHz
× 1

1306 OLED Display


× 1
DFRobot Gravity:Digital Push
Button (Yellow)
× 2

Seeed Grove - 2-Channel SPDT


Relay
× 1

Digilent 5V 2.5A Switching Power


Supply
× 1

SparkFun USB UART Serial


Breakout - CY7C65213
× 1

HC-05 Bluetooth Module

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Hot glue gun (generic)

Tape, Double Sided

Tape, Green
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

This is a replacement part for the washing machine I have that has a broken wash timer. The
original timer was a mechanical timer/direction switch, which can control the washing tub's
motor in following manner:
Take x minutes of wash time input from user
Rotate washing tub's motor clockwise for few seconds
Stop motor for few seconds
Rotate wash tub's motor anti-clockwise for few seconds
Stop motor for few seconds
Keep doing last 4 steps until wash timer expires

Hardware
Arduino Pro Mini: Runs code and controls everything
1306 OLED: Show user instruction and timer countdown
Red/Black Push Button: Set timer and start timer
5V Relay Modules: Supply AC power to motor and control direction
5V Adapter: Power the electronic timer
1306 OLED is directly soldered on the pro mini like this:
Arduino Pro Mini + 1306 OLED
2 relays module, 2 push buttons, Arduino Pro Mini + 1306 OLED is connected on a
protoboard like this -

Hardware
Soldering
Programming
Step 1: Get a HC-05 Bluetooth-Serial module and change it's baud rate to 57600 according
to this tutorial or this step. To perform this step another Arduino Uno or a USB to Serial
module will be required.
Use following AT commands
AT
AT+UART = 57600,0,0
AT+RESET
Step 2: After the baud rate is changed to 57600, connect the HC-05 to
Arduino pro mini according to following wiring diagram
Wireless Programming of Arduino Pro mini with HC-05
Step 3: Select board from Arduino IDE, paste the code and click upload.

Selecting appropriate board


I am using Bluetooth serial, because it enables wireless in system field programmable
capabilities, which helped updating the code on pro mini if needed.
Wiring and Device Operation Explained
Wiring may vary for newer/different washing machine models, so I am going to explain
about my one. Pay attention to the "Sharp" diagram on bottom-right corner, one WHITE
WIRE is coming from mains and going to the wash timer, one RED WIRE and one BLUE
WIRE is coming out of the wash timer. I have disconnected these 3 wires from the original
(faulty) wash timer and brought out through a hole on the top of the washing machine.

Wiring Explained
Broken Mechanical Timer/Motor Direction Control Switch
When WHITE WIRE is switched to the RED WIRE motor rotates in clockwise and when
WHITE WIRE is switched to the BLUE WIRE motor rotates in anticlockwise direction.
This electronic timer made with Arduino pro mini will keep track of wash time, rotate the
wash tub's motor in one direction for 5 seconds by connecting WHITE and RED wires
through one relay contact. Then it will stop the motor and wait for 5 seconds. After that it
will rotate the was tub's motor in the other direction for 5 seconds by connecting the
WHITE and BLUE wires through the other relay contact. Then it will stop and wait for
another 5 seconds. All these timing sequence can be modified from the code if necessary.
Following diagram shows how just flipping the AC incoming mains to one leg or the other
leg of the motor's capacitor, direction of the AC motor can be altered.
AC Induction Motor Direction Control

SCHEMATICS
CODE

#include "U8glib.h"
//SSD1306 oled waveshare(clk,din,cs,d/c,res);
U8GLIB_SSD1306_128X64 u8g(A4,A5,12,11,10);

volatile int rbc = 0;


volatile int bbc = 0;
int sec =0;
int mi = 0;
int motor_rotation = 0;

void setup()
{
u8g.setRot180();
analogReference(INTERNAL);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
attachInterrupt(0, ISR_SW_RED,FALLING);
attachInterrupt(1, ISR_SW_BLACK,FALLING);
pinMode(5,OUTPUT);
digitalWrite(5,LOW);
pinMode(4,OUTPUT);
digitalWrite(4,LOW);
}
void loop(void)
{

while(!rbc)
{
// show timer set menu
u8g.firstPage();
do {
draw_menu();
} while( u8g.nextPage() );

// show user proper operation message


if (rbc>0 && bbc==0)
{
u8g.firstPage();
do {
draw_message();
} while( u8g.nextPage() );
delay(2000);
rbc=0; //u8g.clear();
}
}

// start timer
if(rbc>0)
{
sec =59;
mi = bbc-1;

while(mi>=0)
{
// show countdown timer message
unsigned long temp = millis()+1000;
while(temp>=millis())
{
u8g.firstPage();
do {
draw_timer();
} while( u8g.nextPage() );
}

sec=sec-1;
if(sec%5==0)
{
control_motor(); // call every 5 sec
}
if (sec <= 0)
{
sec = 59;
mi = mi - 1;
}
}
rbc = 0; bbc = 0;
mi = 0 ; sec = 0;
digitalWrite(5,LOW);digitalWrite(6,LOW);
}

}// end of loop

void draw_menu(void)
{
u8g.setFont(u8g_font_timB24);
if (bbc<10)
{
u8g.drawStr( 22,30,"0");
u8g.setPrintPos(38,30);u8g.print(bbc);
}
else
{
u8g.setPrintPos(22,30);u8g.print(bbc);
}
u8g.drawStr( 54,30,":00");
u8g.setFont(u8g_font_8x13);
u8g.drawStr( 0,62," 'WASHING TIMER'");

u8g.setFont(u8g_font_5x8);
u8g.drawStr( 0,47,"Red:START Black:SET TIME");

}
void draw_message(void)
{
u8g.setFont(u8g_font_8x13);
u8g.drawStr( 0,10," SET WASH TIMER");
u8g.drawStr( 0,23,"FIRST BY PUSHING");
u8g.drawStr( 0,36,"THE BLACK BUTTON");
// u8g.setFont(u8g_font_8x13);
u8g.drawStr( 0,62," 'WASHING TIMER'");

u8g.setFont(u8g_font_5x8);
u8g.drawStr( 0,47,"Red:START Black:SET TIME");

void draw_timer(void)
{

u8g.setFont(u8g_font_timB24);
if (mi<10)
{
u8g.drawStr( 22,30,"0");
u8g.setPrintPos(38,30);u8g.print(mi);
}
else
{
u8g.setPrintPos(22,30);u8g.print(mi);
}
u8g.drawStr( 54,30,":");

if (sec<10)
{
u8g.drawStr( 70,30,"0");
u8g.setPrintPos(86,30);u8g.print(sec);
}
else
{
u8g.setPrintPos(70,30);u8g.print(sec);
}

if(motor_rotation==0)
{
u8g.setFont(u8g_font_5x8);
u8g.drawStr( 0,47," WASHING MOTOR CW Spin");
digitalWrite(5,HIGH);
}

if(motor_rotation==1)
{
u8g.setFont(u8g_font_5x8);
u8g.drawStr( 0,47," WASHING MOTOR STOPPED ");
digitalWrite(5,LOW);digitalWrite(4,LOW);
}
if(motor_rotation==2)
{
u8g.setFont(u8g_font_5x8);
u8g.drawStr( 0,47," WASHING MOTOR CCW Spin");
digitalWrite(4,HIGH);

}
if(motor_rotation==3)
{
u8g.setFont(u8g_font_5x8);
u8g.drawStr( 0,47," WASHING MOTOR STOPPED ");
digitalWrite(5,LOW);digitalWrite(4,LOW);

u8g.setFont(u8g_font_8x13);
u8g.drawStr( 0,62," 'WASHING TIMER'");

void ISR_SW_RED()
{
sei();
rbc++;
cli();
}
void ISR_SW_BLACK()
{
sei();
bbc++;
cli();
}

void control_motor()
{
motor_rotation++;
if(motor_rotation>3)
{
motor_rotation = 0;
}
}

58) Arduino IoT IR Programmable Transcoder TV Remote on


Steroids
COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

General Purpose Transistor NPN

× 1

Generic IR LED (940nm)


× 2
IR receiver (generic)
× 2

Generic RGB LED


× 1

Resistor 330 ohm

× 4

Espressif Wemos D1 Mini

× 1

NodeMCU ESP8266 Breakout


Board
× 1

Espressif ESP8266 ESP-12E

× 1

resistor 470 Ohm


× 3

Plastic Enclosure (clear lid)


× 1

Veroboard
× 1

USB-A to Micro-USB Cable


× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

You when something annoys you so much you just have to fix it
especially if every one else nags you. Our television remote falls in this
category, its a "Dick Smith" brand unit and has a dodgy intermittent
remote. I've used universal remotes before and even after hours of
programming them they are not so flash. So what to do? Our Panasonic
DVR we use has a more than adequate universal section built in but in
spite of talking to 100s of other devices our TV is not one of them. If
only it spoke the lingo!
Arduino IR library and Nano on the job
Did you know with a couple of parts you can receive, analyse and send
IR codes with even the smallest Arduino? So with not much more than
the example sketch you can work out what codes in what protocol gets
sent from your remote for each button. With a couple more lines of
code you can send another code that you would like substituted for the
the first code.
So in no time at all you have built yourself a transcoder. Receives
codes of one remote and re-transmits them as if from another. "Piece of
Pi" or maybe Arduino? I even put in the start of an overlay function so
I can use all of the remote buttons for the TV if the original device is
off, I used a RGB LED indicator to show when your in that mode to
avoid user confusion.
Anyhow, all that is left now is to give the remote to family members to
test and suggest while you watch for bugs.
The circuit
Very simple, due to the IR receiver doing a lot of the heavy lifting. It
has the automatic gain control and many other items needed to
successfully demodulate the 38 kHz signal that is passed to the
Arduino. There is no current limmit resistor on the two IR LEDs. I was
expecting scorch marks on the couch while testing but it seems to work
fine at 5V with the LEDs I bought. Trying this was a response to what
seemed a pathetic range at 20 ma, "More power Igor !"

Beta testing, note the recycled mobile phone charger as a power source
You can see the proof of concept test unit with the breadboard to the
left of our TV. The Arduino Nano is mounted on a prototype shield to
the right. These prototype shields are neat as no toolkit should be
without one!
Not all beer and Skittles
There are some subtle things at play in the project and its all in the
timing of the reception and transmission of the new code. but as always
"Professor Google" has most of the answers that you seek.
Worthwhile?
Definitely, I only need one remote which I didn't have to buy. I can
change functionality (Include some macros) if I wish. Most importantly
I learned a lot about IR remote controls.
But wait there's more... ESP to the rescue!
All the parts for the final build sat on my bench for 12 months,
assigned to the back burner after some success with a soldering iron
and the actual TV remote. In the mean time I learned about the
ESP8266. So when it can to put the unit in a box I thought why not
make it run on a NodeMCU board. So with that thought in mind the
final chapter and build was started.

The IR transceiver assembly and status LED


Fitting all the bits in the wee box
The finished unit minus a few wires

Other side showing ESP8266 and all the LED's and IR receiver.
So the software was rearranged and refactored to suit the new and
better IR library for the ESP8266. The tri-color LED was used as
follows. Red flash for IR transmit, Blue flash for WiFi Receive and
Green flash for IR receive. The Blue LED also flashes fast during the
boot phase as it attempts to login to the WiFi. The built in LED is used
as a confidence meter / heart beat.
The unit has both soft AP and WiFi client, This makes configuration
easier as there is always a configuration port available.
The remote control page uses some in-line CSS in the web response to
set the style of the form buttons which form the basis of the remote
control page. The page works nicely on mobile phones due to the
"viewport" command which helps the phone get a better "perspective"
on how it should display the content. These represent a departure from
my usual web M.O but I am trying to "up skill" a bit.
But wait... how could I build a remote control that has WiFi with
making it programmable via the WiFi and IR port. So a new web page
and interface was designed so I could capture an IR code and assign it
to a button in the control matrix. In fact you can reprogram it all via
this interface. There is a factory reset to return it to the original state if
you completely loose your way.
Unit positioned just below the IR receiver on the TV
Final assembled and working unit
Actually I found the virtual remote on a mobile web page much handier
than just a gimmick. Every member of the family has some sort of
device and can now operate the TV even if the remote has scurried
away into the deepest recesses of the sofa.

TV remote as viewed from my phone


Bottom part of the screen... Pop ups be the digital equivalent of fingers
on the lens
Top of code setup page

Bottom of code setup Page


Hmmm.... works well but could be better. I found myself wanting more
devices on the virtual remote. There be enough EEPROM memory so
lets Implement 3 pages of 48 buttons (4 x 12). This doesn't really
impact the rest of the code and really just increases the lookup table for
the transcode function. So that will no doubt be the next improvement..
Something Like this maybe ?
Strangely enough the wee transcoder box helped shine some light on
our troublesome TV remote. I was under the impression it wasn't
transmitting at all. However I noticed the green light flashing (code
received) but the TV not responding. So what curiosity led me to the
setup page where I discovered the remote was sending the wrong
codes! No wonder the TV doesn't respond, but armed with knowledge a
fix may me close at hand.
SCHEMATICS
CODE
// Include the IRremote library header
//
#include <IRremote.h>

#define DECODE_NEC 1
#define TVONOFF 0xFB38C7
#define TVAV 0xFBE817 // signal source
#define TVVOLUP 0xFBD22D
#define TVVOLDN 0xFBF20D
#define TVCHUP 0xFB906F
#define TVCHDN 0xFBA05F
#define TV1PAD 0xFB2AD5
#define TV2PAD 0xFB6897
#define TV3PAD 0xFBA857
#define TV4PAD 0xFB0AF5
#define TV5PAD 0xFB48B7
#define TV6PAD 0xFB8877
#define TV7PAD 0xFB32CD
#define TV8PAD 0xFB708F
#define TV9PAD 0xFBB04F
#define TV0PAD 0xFB30CF
#define TVLNAV 0xFBE21D
#define TVRNAV 0xFBE01F
#define TVUNAV 0xFB58A7
#define TVDNAV 0xFB12ED
#define TVOKNAV 0xFB609F
#define TVAPMENU 0xFB18E7
#define TVEXITNAV 0xFB50AF
#define TVMUTE 0xFB10EF
#define TVPLAY 0xFB5AA5
#define TVPAUSE 0xFB4AB5
#define TVSTOP 0xFBBA45
#define TVWTF 0xFB3AC5
#define TVREW 0xFBAA55
#define TVFF 0xFB7A85
#define TVPREV 0xFB8A75
#define TVNEXT 0xFB9A65
#define TVTEXT 0xFB9A65
#define TVSUBTTL 0xFBFA05
#define TVFREEZE 0xFB9867
#define TVINFO 0xFB1AE5
#define TVRED 0xFB6A95
#define TVGREEN 0xFBEA15
#define TVYELLOW 0xFBF807
#define TVBLUE 0xFBDA25
IRsend irsend;
long PrevCode;
int iMode = 0;
bool bTransmit=false;
bool bRepeat=false;
//------------------------------------------------------------------------------
// Tell IRremote which Arduino pin is connected to the IR Receiver
(TSOP4838)
//
int recvPin = 11;
IRrecv irrecv(recvPin);

//+============================================================
// Configure the Arduino
//
void setup ( )
{
Serial.begin(115200); // Status message will be sent to PC at 9600 baud
Serial.println("Start");
pinMode(3,OUTPUT); // IR LED
pinMode(4,OUTPUT); // RGB LED FOR MODE INDICATOR
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
irrecv.enableIRIn(); // Start the receiver
irrecv.blink13(1);
}

//+============================================================
// Display IR code
//
void ircode (decode_results *results)
{
// Panasonic has an Address
if (results->decode_type == PANASONIC) {
Serial.print(results->address, HEX);
Serial.print(":");
}

// Print Code
Serial.print(results->value, HEX);
}

//+============================================================
// Display encoding type
//
void encoding (decode_results *results)
{
switch (results->decode_type) {
default:
case UNKNOWN: Serial.print("UNKNOWN"); break ;
case NEC: Serial.print("NEC"); break ;
case SONY: Serial.print("SONY"); break ;
case RC5: Serial.print("RC5"); break ;
case RC6: Serial.print("RC6"); break ;
case DISH: Serial.print("DISH"); break ;
case SHARP: Serial.print("SHARP"); break ;
case JVC: Serial.print("JVC"); break ;
case SANYO: Serial.print("SANYO"); break ;
case MITSUBISHI: Serial.print("MITSUBISHI"); break ;
case SAMSUNG: Serial.print("SAMSUNG"); break ;
case LG: Serial.print("LG"); break ;
case WHYNTER: Serial.print("WHYNTER"); break ;
case AIWA_RC_T501: Serial.print("AIWA_RC_T501"); break ;
case PANASONIC: Serial.print("PANASONIC"); break ;
case DENON: Serial.print("Denon"); break ;
}
}

//+============================================================
// Dump out the decode_results structure.
//
void dumpInfo (decode_results *results)
{
// Check if the buffer overflowed
if (results->overflow) {
Serial.println("IR code too long. Edit IRremoteInt.h and increase
RAWLEN");
return;
}

// Show Encoding standard


Serial.print("Encoding : ");
encoding(results);
Serial.println("");

// Show Code & length


Serial.print("Code : ");
ircode(results);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
}

//+============================================================
// Dump out the decode_results structure.
//
void dumpRaw (decode_results *results)
{
// Print Raw data
Serial.print("Timing[");
Serial.print(results->rawlen-1, DEC);
Serial.println("]: ");

for (int i = 1; i < results->rawlen; i++) {


unsigned long x = results->rawbuf[i] * USECPERTICK;
if (!(i & 1)) { // even
Serial.print("-");
if (x < 1000) Serial.print(" ") ;
if (x < 100) Serial.print(" ") ;
Serial.print(x, DEC);
} else { // odd
Serial.print(" ");
Serial.print("+");
if (x < 1000) Serial.print(" ") ;
if (x < 100) Serial.print(" ") ;
Serial.print(x, DEC);
if (i < results->rawlen-1) Serial.print(", "); //',' not needed for last one
}
if (!(i % 8)) Serial.println("");
}
Serial.println(""); // Newline
}

//+============================================================
// Dump out the decode_results structure.
//
void dumpCode (decode_results *results)
{
// Start declaration
Serial.print("unsigned int "); // variable type
Serial.print("rawData["); // array name
Serial.print(results->rawlen - 1, DEC); // array size
Serial.print("] = {"); // Start declaration

// Dump data
for (int i = 1; i < results->rawlen; i++) {
Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
if ( i < results->rawlen-1 ) Serial.print(","); // ',' not needed on last one
if (!(i & 1)) Serial.print(" ");
}

// End declaration
Serial.print("};"); //

// Comment
Serial.print(" // ");
encoding(results);
Serial.print(" ");
ircode(results);

// Newline
Serial.println("");

// Now dump "known" codes


if (results->decode_type != UNKNOWN) {

// Some protocols have an address


if (results->decode_type == PANASONIC) {
Serial.print("unsigned int addr = 0x");
Serial.print(results->address, HEX);
Serial.println(";");
}

// All protocols have data


Serial.print("unsigned int data = 0x");
Serial.print(results->value, HEX);
Serial.println(";");
}
}

//+============================================================
// The repeating section of the code
//
void loop ( )
{
decode_results results; // Somewhere to store the results

if (irrecv.decode(&results)) { // Grab an IR code


dumpInfo(&results); // Output the results
dumpRaw(&results); // Output the results in RAW format
dumpCode(&results); // Output the results as source code
Serial.println(""); // Blank line between entries

// Serial.println(iMode);
Serial.print("R ");
Serial.println(results.value, HEX);

bTransmit = false ;
switch(results.value){
case 0x18E710EF: // TV on off
PrevCode = TVONOFF ;
bTransmit = true ;
bRepeat = false ;
iMode = 0 ;
break;
case 0x18E750AF: // AV
PrevCode = TVAV ;
bTransmit = true ;
bRepeat = false ;
iMode = 0 ;
break;
case 0x18E740BF: // VOL +
PrevCode = TVVOLUP ;
bTransmit = true ;
bRepeat = true ;
iMode = 0 ;
break;
case 0x18E7C03F: // VOL -
PrevCode = TVVOLDN ;
bTransmit = true ;
bRepeat = true ;
iMode = 0 ;
break;
case 0x18E700FF: // CH +
PrevCode = TVCHUP ;
bTransmit = true ;
bRepeat = false ;
iMode = 0 ;
break;
case 0x18E7807F: // CH-
PrevCode = TVCHDN ;
bTransmit = true ;
bRepeat = false ;
iMode = 0 ;
break;
case 0xFFFFFFFF: // repeat code
if ( bRepeat == true ){
bTransmit = true ;
}
break;

case 0xD880287: // blue button


if ( iMode != 1 ){
iMode = 1;
}else{
iMode = 0;
}
bRepeat = false ;
break;
case 0xD88C247: // yellow button
PrevCode = TVMUTE ;
bTransmit = true ;
bRepeat = false ;
iMode = 0 ;
break;
case 0xD8842C7: // green button
if ( iMode != 3 ){
iMode = 2;
}else{
iMode = 0;
}
bRepeat = false ;
break;
case 0xD888207: // red button
if ( iMode != 4 ){
iMode = 3;
}else{
iMode = 0;
}
bRepeat = false ;
break;
case 0xD08E1E4: // left nav
if ( iMode == 1 ){
PrevCode = TVLNAV ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD081114: // right nav
if ( iMode == 1 ){
PrevCode = TVRNAV ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD086164: // down nav
if ( iMode == 1 ){
PrevCode = TVDNAV ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08A1A4: // up nav
if ( iMode == 1 ){
PrevCode = TVUNAV ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD084144: // ok nav
if ( iMode == 1 ){
PrevCode = TVOKNAV ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD888A0F: // exit nav
if ( iMode == 1 ){
PrevCode = TVEXITNAV ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD086663: // status nav
bRepeat = false ;
break;
case 0xD088184: // return nav
bRepeat = false ;
break;
case 0xD08080D: // 1 nav pad
if ( iMode == 1 ){
PrevCode = TV1PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08888D: // 2 nav pad
if ( iMode == 1 ){
PrevCode = TV2PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08484D: // 3 nav pad
if ( iMode == 1 ){
PrevCode = TV3PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08C8CD: // 4 nav pad
if ( iMode == 1 ){
PrevCode = TV4PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08282D: // 5 nav pad
if ( iMode == 1 ){
PrevCode = TV5PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08A8AD: // 6 nav pad
if ( iMode == 1 ){
PrevCode = TV6PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08686D: // 7 nav pad
if ( iMode == 1 ){
PrevCode = TV7PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08E8ED: // 8 nav pad
if ( iMode == 1 ){
PrevCode = TV8PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08181D: // 9 nav pad
if ( iMode == 1 ){
PrevCode = TV9PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
case 0xD08989D: // 0 nav pad
if ( iMode == 1 ){
PrevCode = TV0PAD ;
bTransmit = true ;
bRepeat = false ;
}
break;
default:
bTransmit = false ;
bRepeat = false ;
break;
}
if ( bTransmit ){
Serial.print("T ");
Serial.println(PrevCode, HEX);
irsend.sendNEC(PrevCode,32);
bTransmit = false ;
}
delay(50);
irrecv.resume(); // Prepare for the next value
irrecv.enableIRIn(); // Start the receiver
irrecv.blink13(1);
}

}
59) Arduino Weather Wand

COMPONENTS AND SUPPLIES


SparkFun Arduino Pro Mini 328 -
3.3V/8MHz
× 1

TMP36 sensor
× 1

NeoPixel RGB LED


× 1
100 Ohm resistor (Green and Blue
channel) × 2

150 Ohm resistor (red channel)


× 1

110mah 3.7v lipo battery


× 1

ABOUT THIS PROJECT


The wondrous magical weather wand casts an enchanting spell of light.
Away to make the invisible visible.
In less magical terms, I have an Arduino pro mini with a temperature
sensor (currently a TMP36) and a RGB LED. The Arduino checks
temperatures and sets the color of the light based on the temperature.
The early version of this used a temp to color table (like the temperature
map project) that would for example set to the light yellow if above 70º or
to blue if below 30º. However it would be pretty unlikely to encounter that
wide of a temperature range within a space so instead of re-tuning the
table for every location I wanted to have it set it's own range.
The solution was to use statistics! It takes and averages the temperatures it
sees and sets the color to normal (green) based on that average. The
standard deviation (ie max/min range) is set based on the variation the
sensor picks up. The color changes based not on a specific temp value but
the number of standard deviations from that average. ie: 2+ stddev is red
-2 stddev is purple, etc.
Testing the temperature variations around the room
Making of

Breadboard prototype with the v2 being built.


Resistor pack for the LED
working prototype

TMP36 and RGB LED at the tip


Future plans:
Would like to make a nice magic wand case, maybe fimo clay or
something.
Experimenting with timing and other sensors to get a faster response rate
and better sensitivity to change.
Might work on gradients between values instead of 'click-stops' for color
change values.
Add a small capacitor to the TMP36 power input to stabilize it. (Currently
stabilizing in code and it is slowing response times)
Quicky breadboard version of the NeoPixel weather wand
SCHEMATICS

Wiring for RGB LED use

Wiring for NeoPixel use


1000uF cap on pixel power, 3-500 ohm resistor on data, also added a
.1uF cap to stabilize the TMP36
CODE

wx_wand_1.txtC/C++

/*
The Weather Wand!
A small wand that lights up at the tip based on if it is hot or cold.
Hot and cold are determined by the standard deviation from the average of
the 50 most recent temperature samples.
Hardware: An Arduino pro mini with a TMP36 temp sensor and an
common cathode RGB LED.

*/
//________________Setup________________________

int DEBUG = 1; // DEBUG counter; if set to 1, will write values back


via serial

// Init the Pins used for PWM


const int redPin = 3;
const int greenPin = 5;
const int bluePin = 6;

//Temp sensor stuff


int sensorPin = 0; //TMP36
float tempF;
float tempC;

// Vars for the color output


int redVal = 0;
int grnVal = 0;
int bluVal = 0;

//delay var
int del = 100;

//statistics
int max_samples = 50;
int temperature_samples[50];
int n_temperature_samples = 0;
int i_temperature_samples = 0;
float stddev_temperature = 5;
float avg_temperature = 50;
float tempF_recent = 0;

//________________Run Time________________________

void setup()
{
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);

if (DEBUG) { // If we want to see values for debugging...


Serial.begin(9600); // ...set up the serial ouput
Serial.println("Starting");
}
}

void loop()
{
getTemp();

temperature_samples[i_temperature_samples] = tempF;
i_temperature_samples++;
if (n_temperature_samples < max_samples) {
n_temperature_samples++;
}
if (i_temperature_samples >= max_samples) {
i_temperature_samples = 0;
}

computeStdDev();

tempColor();

delay(del);
}

// ---------------- Function Fun --------------------

void getTemp()
{
//getting the voltage reading from the temperature sensor
int reading = analogRead(sensorPin);

// converting that reading to voltage, for 3.3v arduino use 3.3, for 5v use 5
float voltage = reading * 3.3;
voltage /= 1024.0;

// now kick out the temperature


tempC = (voltage - 0.5) * 100 ; //converting from 10 mv per degree with
500 mV offset
//to degrees ((voltage - 500mV) times 100)

// Convert to Fahrenheit
tempF = (tempC * 9.0 / 5.0) + 32.0;

if (DEBUG) // If we want to print it all to console...


{
Serial.println("++++++++++++++");
Serial.print(voltage); Serial.println(" volts");
Serial.print(tempC); Serial.println(" degrees C");
Serial.print(tempF); Serial.println(" degrees F");
Serial.print(tempF_recent); Serial.println(" degrees F (recent)");

Serial.println("--------------");
}

void computeStdDev() {
int i;
avg_temperature = 0;
for (i = 0; i < n_temperature_samples; i++){
avg_temperature = avg_temperature + temperature_samples[i];
}
avg_temperature = avg_temperature / n_temperature_samples;
stddev_temperature = 0;
for (i = 0; i < n_temperature_samples; i++){
stddev_temperature = stddev_temperature + (temperature_samples[i] -
avg_temperature) * (temperature_samples[i] - avg_temperature);
}

stddev_temperature = stddev_temperature / n_temperature_samples;


stddev_temperature = sqrt(stddev_temperature);

int start_i = i_temperature_samples - 5;


if (start_i < 0) {
start_i = 0;
}

if (i_temperature_samples - start_i > 0){

tempF_recent = 0;
for (i = start_i; i < i_temperature_samples; i++) {
tempF_recent = tempF_recent + temperature_samples[i];
}
tempF_recent /= (i_temperature_samples - start_i);

} else {
tempF_recent = tempF;
}

if (DEBUG) // If we want to print it all to console...


{
Serial.print("n_temperature_samples: ");
Serial.println(n_temperature_samples);
Serial.print("avg_temperature: ");
Serial.println(avg_temperature);
Serial.print("temperature: ");
Serial.println(tempF);
Serial.print("i: ");
Serial.println(i_temperature_samples);
Serial.print("stddev_temperature: ");
Serial.println(stddev_temperature);
}
}

//Set the RGB color based on standard deviation distance from average
temp
void tempColor()
{
float diff = (tempF_recent - avg_temperature) / stddev_temperature;

if(diff < -2.5) {


setColor(255, 0, 255);
} else if (diff < -2.0) {
setColor(0, 100, 255);
} else if (diff < -1.5) {
setColor(0, 157, 200);
} else if (diff < -1.0) {
setColor(150, 206, 150);
} else if (diff < -0.5) {
setColor(0, 200, 50);
} else if (diff < 0.0) {
setColor(0, 255, 1);
} else if (diff < 0.5) {
setColor(150, 255, 0);
} else if (diff< 1.0) {
setColor(200, 200, 0);
} else if (diff < 1.5) {
setColor(255, 100, 0);
} else if (diff < 2.0) {
setColor(255, 10, 0);
} else {
setColor(100, 100, 100); //out of scope color
}

if (DEBUG) // Standard deviation visualizer


{
Serial.print("diff: ");
Serial.println(diff);

if(diff < -2.5) {


Serial.println("X----0+++++");
} else if (diff < -2.0) {
Serial.println("-X---0+++++");
} else if (diff < -1.5) {
Serial.println("--X--0+++++");
} else if (diff < -1.0) {
Serial.println("---X-0+++++");
} else if (diff < -0.5) {
Serial.println("----X0+++++");
} else if (diff < 0.0) {
Serial.println("-----0+++++");
} else if (diff < 0.5) {
Serial.println("-----0X++++");
} else if (diff< 1.0) {
Serial.println("-----0+X+++");
} else if (diff < 1.5) {
Serial.println("-----0++X++");
} else if (diff < 2.0) {
Serial.println("-----0+++X+");
} else {
Serial.println("X----0++++X");
}
}
}

//Send the RGB value to the color pins


void setColor(int r, int g, int b) //0-255 input
{
// plug it in
int redVal = r;
int grnVal = g;
int bluVal = b;

analogWrite(redPin, redVal); // Write current values to LED pins


analogWrite(greenPin, grnVal);
analogWrite(bluePin, bluVal);

if (DEBUG) // If we want to print it all to console...


{
Serial.print(redVal); Serial.print(" R ");
Serial.print(grnVal); Serial.print(" G ");
Serial.print(bluVal); Serial.println(" B ");
Serial.println("--------------");
}
}

file_15302.txtC/C++

/*
The Weather Wand!
A small wand that lights Neo Pixels (addressable RGB LEDs) at the tip in
response to temperature .
Hot and cold are determined by the standard deviation from the average of
the 50 most recent temperature samples.
Hardware: An Arduino pro mini with a TMP36 temp sensor and
addressable RGB LEDs.
NeoPixel library from Adafruit
*/

//________________Setup________________________

int DEBUG = 1; // DEBUG counter; if set to 1, will write values back


via serial

// NeoPixel setup
#include <Adafruit_NeoPixel.h>
#define PIN 6

// Parameter 1 = number of pixels in strip


// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products
w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels,
WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel
products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels,
not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(12, PIN, NEO_GRB +
NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor


across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid
connecting
// on a live circuit...if you must, connect GND first.

//Temp sensor setup


int sensorPin = 0; //TMP36
float tempF;
float tempC;

//delay var
int del = 80;

//statistics
int max_samples = 50;
int temperature_samples[50];
int n_temperature_samples = 0;
int i_temperature_samples = 0;
float stddev_temperature = 5;
float avg_temperature = 50;
float tempF_recent = 0;

//________________Run Time________________________

void setup()
{
strip.begin();
strip.show(); // Initialize all pixels to 'off'
strip.setBrightness(50); // Turn down for what 0-255

if (DEBUG) { // If we want to see values for debugging...


Serial.begin(9600); // ...set up the serial ouput
Serial.println("Starting");
}
}

void loop()
{
getTemp();

temperature_samples[i_temperature_samples] = tempF;
i_temperature_samples++;
if (n_temperature_samples < max_samples) {
n_temperature_samples++;
}
if (i_temperature_samples >= max_samples) {
i_temperature_samples = 0;
}

computeStdDev();

tempColor();

delay(del);
}

// ---------------- Function Fun --------------------

void getTemp()
{
//getting the voltage reading from the temperature sensor
int reading = analogRead(sensorPin);

// converting that reading to voltage, for 3.3v arduino use 3.3, for 5v use 5
float voltage = reading * 3.3;
voltage /= 1024.0;

// now kick out the temperature


tempC = (voltage - 0.5) * 100 ; //converting from 10 mv per degree with
500 mV offset
//to degrees ((voltage - 500mV) times 100)

// Convert to Fahrenheit
tempF = (tempC * 9.0 / 5.0) + 32.0;

if (DEBUG) // If we want to print it all to console...


{
Serial.println("++++++++++++++");
Serial.print(voltage); Serial.println(" volts");
Serial.print(tempC); Serial.println(" degrees C");
Serial.print(tempF); Serial.println(" degrees F");
Serial.print(tempF_recent); Serial.println(" degrees F (recent)");
Serial.println("--------------");
}

}//end

void computeStdDev() {
int i;
avg_temperature = 0;

for (i = 0; i < n_temperature_samples; i++){


avg_temperature = avg_temperature + temperature_samples[i];
}

avg_temperature = avg_temperature / n_temperature_samples;

stddev_temperature = 0;
for (i = 0; i < n_temperature_samples; i++){
stddev_temperature = stddev_temperature + (temperature_samples[i] -
avg_temperature) * (temperature_samples[i] - avg_temperature);
}

stddev_temperature = stddev_temperature / n_temperature_samples;


stddev_temperature = sqrt(stddev_temperature);

int start_i = i_temperature_samples - 5;


if (start_i < 0) {
start_i = 0;
}

if (i_temperature_samples - start_i > 0){

tempF_recent = 0;
for (i = start_i; i < i_temperature_samples; i++) {
tempF_recent = tempF_recent + temperature_samples[i];
}
tempF_recent /= (i_temperature_samples - start_i);

} else {
tempF_recent = tempF;
}

if (DEBUG) // If we want to print it all to console...


{
Serial.print("n_temperature_samples: ");
Serial.println(n_temperature_samples);
Serial.print("avg_temperature: ");
Serial.println(avg_temperature);
Serial.print("temperature: ");
Serial.println(tempF);
Serial.print("i: ");
Serial.println(i_temperature_samples);
Serial.print("stddev_temperature: ");
Serial.println(stddev_temperature);
}
}//end

//Set the RGB color based on standard deviation distance from average
temp
void tempColor()
{
float diff = (tempF_recent - avg_temperature) / stddev_temperature;

if(diff < -2.5) {


setColor(strip.Color(255, 0, 255));
} else if (diff < -2.0) {
setColor(strip.Color(0, 100, 255));
} else if (diff < -1.5) {
setColor(strip.Color(0, 157, 200));
} else if (diff < -1.0) {
setColor(strip.Color(150, 206, 150));
} else if (diff < -0.5) {
setColor(strip.Color(0, 230, 50));
} else if (diff < 0.0) { // 0 = Avg
setColor(strip.Color(0, 255, 1));
} else if (diff < 0.5) {
setColor(strip.Color(50, 230, 0));
} else if (diff< 1.0) {
setColor(strip.Color(200, 200, 0));
} else if (diff < 1.5) {
setColor(strip.Color(255, 100, 0));
} else if (diff < 2.0) {
setColor(strip.Color(255, 50, 0));
} else {
setColor(strip.Color(255, 0, 0)); //max out color
}

if (DEBUG) // Standard deviation visualizer


{
Serial.print("diff: ");
Serial.println(diff);

if(diff < -2.5) {


Serial.println("X----0+++++");
} else if (diff < -2.0) {
Serial.println("-X---0+++++");
} else if (diff < -1.5) {
Serial.println("--X--0+++++");
} else if (diff < -1.0) {
Serial.println("---X-0+++++");
} else if (diff < -0.5) {
Serial.println("----X0+++++");
} else if (diff < 0.0) {
Serial.println("-----0+++++");
} else if (diff < 0.5) {
Serial.println("-----0X++++");
} else if (diff< 1.0) {
Serial.println("-----0+X+++");
} else if (diff < 1.5) {
Serial.println("-----0++X++");
} else if (diff < 2.0) {
Serial.println("-----0+++X+");
} else {
Serial.println("X----0++++X");
}
}
} //end

//Send the RGB value to the pixels


void setColor(uint32_t c) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
}
} //end

60) Arduino Air Meter Making


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

DHT11 Temperature & Humidity


Sensor (3 pins)
× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


I learned to use the WiFi module last time. This time we will look at
the most important temperature and humidity sensors in this project.
Step 01
A dedicated library is required to use the DHT 11 module. Download
the file below.
File
01 http://deneb21.tistory.com/attachment/cfile24.uf@220A6C3755DA9E322E7FED
Once you have downloaded the file, load DHT 11 from the library.
If the file is successfully loaded, the following screen appears.
Step 02
Now let's look at temperature and humidity with DHT 11 module.
Once you have entered the code and clicked Upload, you can see the
temperature and humidity by checking the serial monitor.
Now we know how to use the DHT 11 module!
Next time, I will work on sending the temperature and humidity data to
the server using ESP-01 module and DHT 11 module learned earlier.

SCHEMATICS

CODE

#include <DHT11.h> //Load library


int pin=2; //Pin number of the signal
DHT11 dht11(pin);
void setup()
{
Serial.begin(9600); //Communication speed setting
}

void loop()
{
int err;
float temp, humi;
if((err=dht11.read(humi, temp))==0) //Read temperature, humidity read
{
Serial.print("temperature:");
Serial.print(temp);
Serial.print(" humidity:");
Serial.print(humi);
Serial.println();
}
else //Processing in case of error
{
Serial.println();
Serial.print("Error No :");
Serial.print(err);
Serial.println();
}
delay(1000); //Repeat every second
}

61) Arduino Kayak GPS Navigation


COMPONENTS AND SUPPLIES
Arduino Nano R3

× 1

TinyCircuits TinyShield GPS

× 1

TinyCircuits TinyDuino Starter Kit


– Lithium Version
× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Latitude and Longitude
Solar Panel
Speed, Odomètre and Time
Speed, Azimut, Time, Tide Clock
Latitude and Longitude

I make this GPS for my kayak. I want to be sufficiently robust to


permanently attached to it (sea condition) and can be run forever for
long sea kayak excursions.
-GPS is powered only by solar energy and can run 1-2 days without sun
if need with a integrate lithium-ion battery (if the battery is full).
-Screen can be read in the sunlight or night with back light LED. On
sunlight the back light LED is turns OFF for reduce the consumption.
-Waterproof, epoxy sealed .
-Tide clock base on moon rotation 12 heures 25 minutes and 14
secondes. hours until low or high tide are display has a count-down of
hours from 5 to 1
-The GPS doesn't have integrate map and should be use in conjunction
with paper map for route planning or can simply use for to see speed,
time and odometer as a dashboard.
-GPS Info available: Time, Latitude and Longitude, Speed, Tide Clock,
Azimuth compass rose, Azimuth Returns/distance and Odometer,
-Pro mode display; Display Speed, Time, Azimuth/compass rose , and
alternatively Azimuth/distance, Tide clock and Odometer
-Dashboard mode display; Big character speed, odometer, time.
-controlled by 4 push buttons (select, Up, Down and Power ON)
-the power on / off are controlled by the MCU and the MCU can turn
off if the battery voltage is too low (battery protection).
-low energy mode, the GPS module is put in sleeping mode for 10 sec
and Hot Start to get data and back on Sleeping Mode...
Next generation will use Arduino Nano pro, GPS module and LCD
display at 3.3 volts, more efficient with 3.7 battery. Controlled by tree
push buttons (select/PowerON, Up and Down) , It will be smaller.
better box design, new option Navigation flashing light (Red and
Green). may be a integrate a buzzer for alarm clock. temperature info.

SCHEMATICS
CODE

/*
*/

#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <avr/pgmspace.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //8>RS,9>E, 4-7>D4-D7,RW>0V,
SoftwareSerial gpsSerial(2, 3); //RX, TX 2>bleuTX, 3>VertRX
TinyGPS gps;

byte clo_n = 0;
boolean eco_mode = false;
boolean pro_mode = false;
static int vref = 211; // 1023/4.9 volts
byte solPanel = 3; //pin
byte batt = 4; //pin
byte LCD_LED = 11;
byte power_pin = 12;
byte sw_sel = 14;// select
byte sw_up = 15;// up
byte sw_dwn = 16;//down
byte fonction = 0;
int gmt;//, hr ;
long Year_Min;
long Tide_one;
unsigned long time_On;
unsigned long time_run;
unsigned long time_old;

int year;//, vinfo;


int menu_index = 0;
int cum_n;
static float rad2deg = 0.01745;
float Odometre;
char msg[6];
byte LCD_LED_N = 220; //OFF 0-a-255 ON
byte col, row, nb = 0, bc = 0; // general
byte bb[8];
byte month, day, hour, minute, second, sped; //hundredths,
long lat, lon; //, latmin, lonmin; //angle
long lat2 = 0;
long lon2 = 0;
long wp_lat, wp_lon ;

const char*azimuts[] = {"N ", "NE ", "E ", "SE ", "S ", "SW ", "W ", "NW " };
const char custom[][8] PROGMEM = { // Custom character definitions
{ 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 }, // char 1
{ 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 2
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03 }, // char 3
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 4
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 }, // char 5
{ 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F }, // char 6
{ 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 7
{ 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 8

};
const char bigChars[][8] PROGMEM = {
{ 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Space
{ 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // !
{ 0x05, 0x05, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00 }, // "
{ 0x04, 0xFF, 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01 }, // #
{ 0x08, 0xFF, 0x06, 0x07, 0xFF, 0x05, 0x00, 0x00 }, // $
{ 0x01, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x04 }, // %
{ 0x08, 0x06, 0x02, 0x20, 0x03, 0x07, 0x02, 0x04 }, // &
{ 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // '
{ 0x08, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 }, // (
{ 0x01, 0x02, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00 }, // )
{ 0x01, 0x04, 0x04, 0x01, 0x04, 0x01, 0x01, 0x04 }, // *
{ 0x04, 0xFF, 0x04, 0x01, 0xFF, 0x01, 0x00, 0x00 }, // +
{ 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //
{ 0x04, 0x04, 0x04, 0x20, 0x20, 0x20, 0x00, 0x00 }, // -
{ 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // .
{ 0x20, 0x20, 0x04, 0x01, 0x04, 0x01, 0x20, 0x20 }, // /
{ 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00 }, // 0
{ 0x01, 0x02, 0x20, 0x04, 0xFF, 0x04, 0x00, 0x00 }, // 1
{ 0x06, 0x06, 0x02, 0xFF, 0x07, 0x07, 0x00, 0x00 }, // 2
{ 0x01, 0x06, 0x02, 0x04, 0x07, 0x05, 0x00, 0x00 }, // 3
{ 0x03, 0x04, 0xFF, 0x20, 0x20, 0xFF, 0x00, 0x00 }, // 4
{ 0xFF, 0x06, 0x06, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 5
{ 0x08, 0x06, 0x06, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 6
{ 0x01, 0x01, 0x02, 0x20, 0x08, 0x20, 0x00, 0x00 }, // 7
{ 0x08, 0x06, 0x02, 0x03, 0x07, 0x05, 0x00, 0x00 }, // 8
{ 0x08, 0x06, 0x02, 0x07, 0x07, 0x05, 0x00, 0x00 }, // 9
};

const static byte gpsDefault[] PROGMEM = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x07, 0x1F, 0x9E};
const static byte gpsSave[] PROGMEM = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x31, 0xBF,
0x13};
const static byte gpsSleep[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x08,
0x00, 0x16, 0x74};
const static byte gpsHot[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x02,
0x00, 0x10, 0x68};
const static byte Disable_GPDTM[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x44, 0x54, 0x4d, 0x2a, 0x33, 0x42, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x0a, 0x00, 0x04, 0x23}; //->Disable_GPDTM
const static byte Disable_GPGBS[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x47, 0x42, 0x53, 0x2a, 0x33, 0x30, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x09, 0x00, 0x03, 0x21}; //->Disable_GPGBS
const static byte Disable_GPGGA[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x47, 0x47, 0x41, 0x2a, 0x32, 0x37, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x00, 0x00, 0xfa, 0x0f}; //>Disable_GPGGA
const static byte Disable_GPGLL[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x47, 0x4c, 0x4c, 0x2a, 0x32, 0x31, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x01, 0x00, 0xfb, 0x11}; //->Disable_GPGLL
const static byte Disable_GPGRS[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x47, 0x52, 0x53, 0x2a, 0x32, 0x30, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x06, 0x00, 0x00, 0x1b}; //->Disable_GPGRS
const static byte Disable_GPGSA[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x47, 0x53, 0x41, 0x2a, 0x33, 0x33, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x02, 0x00, 0xfc, 0x13}; //->DisableGPGSA
const static byte Disable_GPGST[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x47, 0x53, 0x54, 0x2a, 0x32, 0x36, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x07, 0x00, 0x01, 0x1d}; //->Disable_GPGST
const static byte Disable_GPGSV[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x47, 0x53, 0x56, 0x2a, 0x32, 0x34, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x03, 0x00, 0xfd, 0x15}; //->Disable_GPGSV
const static byte Disable_GPRMC[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x52, 0x4d, 0x43, 0x2a, 0x33, 0x41, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x04, 0x00, 0xfe, 0x17}; //->Disable_GPRMC
const static byte Disable_GPVTG[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x56, 0x54, 0x47, 0x2a, 0x32, 0x33, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x05, 0x00, 0xff, 0x19}; //->Disable_GPVTG
const static byte Disable_GPZDA[] PROGMEM = {0x24, 0x45, 0x49, 0x47, 0x50, 0x51,
0x2c, 0x5a, 0x44, 0x41, 0x2a, 0x33, 0x39, 0x0d, 0x0a, 0xb5, 0x62, 0x06, 0x01, 0x03,
0x00, 0xf0, 0x08, 0x00, 0x02, 0x1f}; //->Disable_GPZDA

///////////////////////////////////////////////////////
// Minute depuis debut annee //
///////////////////////////////////////////////////////
int days[] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // Number of days
at the beginning of the month in a not leap year.
long DofY(int yr, int mo, int dy, int h, int mi)
{
int DfY;
long Min2Date;
if (mo == 1 || mo == 2)
{
DfY = days[mo] + dy - 1; //for any type of year, it calculate the number of days
for January or february
}
else if ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0)
{
DfY = days[mo] + dy + 1 - 1;
}
else
{
DfY = days[mo] + dy - 1;
}
Min2Date = (long)DfY * 1440l + (long)h * 60l + (long)mi;
return (Min2Date);
}
///////////////////////////////////////////////////////
// SETUP //
///////////////////////////////////////////////////////
void setup()
{
pinMode(power_pin, OUTPUT);
digitalWrite (power_pin, HIGH); // POWER ON!
analogReference(DEFAULT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.begin(9600);
gpsSerial.begin(9600);
pinMode(LCD_LED, OUTPUT);
//pinMode(buz, OUTPUT);
pinMode(sw_sel, INPUT);
pinMode(sw_up, INPUT);
pinMode(sw_dwn, INPUT);
lcd.begin(16, 2);
analogWrite(LCD_LED, 100);

///////////////////////////////////////////////////////
// EE PROM Variable //
///////////////////////////////////////////////////////
hour = EEPROM.read(0); //lire le gmt
pro_mode = EEPROM.read(4);
EEPROM.get(10, wp_lat);
EEPROM.get(15, wp_lon);
EEPROM.get(20, Tide_one);
EEPROM.get(25, Odometre);
EEPROM.get(30, time_On);
if (isnan(Odometre)) // test if NAN value
{
Odometre = 0;
}
if (hour > 127) //numbre negatif
{
gmt = hour - 256;
}
else
{
gmt = hour;
}
///////////////////////////////////////////////////////
/// REV ///
///////////////////////////////////////////////////////
lcd.clear();
lcd.print(F("Ultimate YAK GPS"));
lcd.setCursor(0, 1);
lcd.print(F("GPS_1602B rev 92.1")); // Revision Version<<<<
delay (2000);
lcd.clear();
lcd.print("GMT="); lcd.print(gmt);
float vbatt = (float) analogRead(batt) / vref + .21; //
lcd.setCursor(0, 1);
lcd.print(F("Batterie:"));
lcd.print(vbatt);
lcd.print("V");
delay (2000);
lcd.clear();
lcd.print(F("Odometre:"));
lcd.print(Odometre);
delay (2000);
lcd.clear();
lcd.print("WPLat:");
lcd.print(wp_lat);
lcd.setCursor(0, 1);
lcd.print("WPLon:");
lcd.print(wp_lon);
delay (2000);
lcd.clear();
lcd.print("Last Time ON:");
lcd.setCursor(0, 1);
lcd.print(time_On / 60000); lcd.print("Min");
delay (4000);

/*lcd.clear();
lcd.print("TIDE: ");
lcd.print(Tide_one);
float a = (float)Tide_one / 288; //288 = 24hr * 60/ 5 min/hr)
int tide_jr = (int)a;
float b = (a - (float) tide_jr) * 24;
tide_hr = (int)b;
tide_min = (b - (float) tide_hr) * 60 ;
lcd.setCursor(0, 1);
lcd.print(tide_jr + 1);
lcd.print("Days ");
lcd.print(tide_hr);
lcd.print(":");
lcd.print(tide_min);
delay(2000);
*/

if (vbatt < 2.8)//volts


{
lcd.setCursor(0, 1); lcd.print("Batt. LOW!");
delay (4000);
//digitalWrite(power_pin, LOW); //off
}
analogWrite(LCD_LED, 20);

///////////////////////////////////////////////////////
// GPS Reset //
///////////////////////////////////////////////////////
lcd.clear();

if (gps.encode(gpsSerial.read()))
{
lcd.print("GPS Reset");
gpsSerial.write(gpsHot, sizeof(gpsHot)); gpsSerial.flush();
gpsSerial.write( gpsDefault, sizeof( gpsDefault)); gpsSerial.flush();
gpsSerial.write( Disable_GPDTM, sizeof( Disable_GPDTM)); gpsSerial.flush();
gpsSerial.write( Disable_GPGBS, sizeof( Disable_GPGBS)); gpsSerial.flush();
gpsSerial.write( Disable_GPGLL, sizeof( Disable_GPGLL)); gpsSerial.flush();
gpsSerial.write( Disable_GPGRS, sizeof( Disable_GPGRS)); gpsSerial.flush();
gpsSerial.write( Disable_GPGSA, sizeof( Disable_GPGSA)); gpsSerial.flush();
gpsSerial.write( Disable_GPGSV, sizeof( Disable_GPGSV)); gpsSerial.flush();
gpsSerial.write( Disable_GPVTG, sizeof( Disable_GPVTG)); gpsSerial.flush();
gpsSerial.write( Disable_GPGGA, sizeof( Disable_GPGGA)); gpsSerial.flush();
}
lcd.setCursor(0, 1); lcd.println(F("Wait satellites."));
///////////////////////////////////////////////////////
/// create 8 custom characters ///
///////////////////////////////////////////////////////
for (nb = 0; nb < 8; nb++ )
{
for (bc = 0; bc < 8; bc++)
bb[bc] = pgm_read_byte( &custom[nb][bc] );
lcd.createChar ( nb + 1, bb );
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// LOOP ///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
while (gpsSerial.available()) // check for gps data
{
if (gps.encode(gpsSerial.read())) // encode gps data
{
gps.get_position(&lat, &lon); // get lat and long
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second);
lat = lat / 100; //enlever les d-secondes
lon = lon / 100;
// lcd.setCursor(0, 0); lcd.print (lat); lcd.print (" "); lcd.print (lon); delay (4000);
hour = hour + gmt;
if (hour > 128) // reference a gmt
{
hour = hour + 24;
day = day - 1;
}
////Serial.print ("DofY=");//Serial.println (DofY (year,month,day,hour,minute));
//Serial.print (year); //Serial.print ("/"); //Serial.print (month); //Serial.print ("/");
//Serial.print (day); //Serial.print (" "); //Serial.print (hour); //Serial.print (":");
//Serial.println (minute);
Year_Min = DofY ((int)year, (int)month, (int)day, (int)hour, (int)minute);
//Serial.print ("Year2min ="); //Serial.println (Year_Min);

if (digitalRead(sw_sel) == LOW) {
lcd.clear();
while (digitalRead(sw_sel) == 0) {} // wait for release
menu(0);
}
if (digitalRead(sw_dwn) == LOW)
{
lcd.clear();
while (digitalRead(sw_dwn) == 0) {} // wait for release
if (pro_mode == false)
{
lcd.clear(); lcd.print("PRO Display ");
delay (1500);
pro_mode = true;
EEPROM.write(4, pro_mode);
}
else
{
lcd.clear(); lcd.print("Dashboard MODE ");
pro_mode = false;
EEPROM.write(4, pro_mode);
delay (1500);
}
lcd.clear ();
}
///////////////////////////////////////////////////////
// LCD LED & test de batt //
///////////////////////////////////////////////////////
float vsol = (float) analogRead(solPanel) / vref ; // 1024/2.5voltsRef
if (eco_mode == true) {
LCD_LED_N = 20;
}
else {
LCD_LED_N = 150;
}
if (vsol > 1) {//volt
vsol = 1;//volt
}
LCD_LED_N = LCD_LED_N - (vsol * LCD_LED_N);
analogWrite(LCD_LED, LCD_LED_N);

float vbatt = (float) analogRead(batt) / vref + .21; // 1024/5voltsRef


if (vbatt < 2.8) // Volts 2.8
{
lcd.clear(); lcd.print("LOW BATT ");
lcd.setCursor(0, 1); lcd.print(vbatt); lcd.print("Volts");
EEPROM.put(25, Odometre); //save odometre
delay (5000);
digitalWrite(power_pin, LOW);// power off
}
if (vbatt > 4.2) // Volts
{
analogWrite(LCD_LED, 255);
digitalWrite(LED_BUILTIN, HIGH);
}
else
{
digitalWrite(LED_BUILTIN, LOW);
}
float speedf = gps.speed() * .01852; // 1.852 /100 knot to kmph
if (speedf < .5)
{
speedf = 0;
}
///////////////////////////////////////////////////////
/// ODOMETRE ///
///////////////////////////////////////////////////////
if (cum_n >= 10)
{
if (lat2 == 0)
{
lat2 = lat;
lon2 = lon;
}
cum_n = 0;
float lon2_dec = lon2 / 10000.0;
/////////////////////convert decimal degree into radian////////////////
float lat1_Rad = lat / 10000.0 * rad2deg;
float lon1_Rad = lon / 10000.0 * rad2deg;
float lat2_Rad = lat2 / 10000.0 * rad2deg;
float lon2_Rad = lon2 / 10000.0 * rad2deg;

//Calculate the distance KM


float latSin = sin((lat1_Rad - lat2_Rad) / 2);
float lonSin = sin((lon1_Rad - lon2_Rad) / 2);

float P2P = 2 * asin(sqrt((latSin * latSin) + cos(lat1_Rad) * cos(lat2_Rad) * (lonSin *


lonSin)));
P2P = P2P * 6371; //Earth radius = 6,371 km

if (P2P < 5 && speedf != 0) // plus de 5 km est une erreur ou speed =0kmh
{
Odometre += P2P;
lat2 = lat;
lon2 = lon;
EEPROM.put(25, Odometre);
time_run = time_run + (millis() - time_old);

EEPROM.put(30, millis()); //future reference


}
time_old = millis();
}
else
{
cum_n ++;
}
///////////////////////////////////////////////////////
// VITESSE //
///////////////////////////////////////////////////////

dtostrf (speedf, 3, 1, msg) ;


if (pro_mode == false)
{
writeBigString(msg, 0, 0);
lcd.setCursor(7, 0); lcd.print ("KM ");
lcd.setCursor(7, 1); lcd.print ("/H ");
lcd.setCursor(10, 0);
if (Odometre < 100)
{
dtostrf (Odometre, 1, 1, msg) ;
}
else
{
dtostrf (Odometre, 1, 0, msg) ;
}
lcd.print (msg); lcd.print ("KM ");

horloge (10, 1);


}
else
{
lcd.setCursor(0, 0);
lcd.print(msg); lcd.print("KMH ");//dtostrf (speedf, 3, 1, msg) ;
Print_Azimut(8, 0);
horloge(0, 1) ;
///////////////////////////////////////////////////////
// Display Fonction Variable //
///////////////////////////////////////////////////////
fonction++;
switch (fonction / 3)
{
case 1:
{
Print_wpazimut(6, 1);
EEPROM.put(30, millis());
}
break;
case 4:
{
Print_Tide(6, 1);
}
break;
case 2:
{
lcd.setCursor(6, 1);
if (Odometre < 100)
{
dtostrf (Odometre, 1, 1, msg) ;
}
else
{
dtostrf (Odometre, 1, 0, msg) ;
}
lcd.print ("Od:"); lcd.print (msg); lcd.print ("KM ");
}
break;
case 3:
{
lcd.setCursor(6, 1);
lcd.print ("Run:");
if (time_run > 10000000L)//msec
{
lcd.print (time_run / 3600000L);//msec
lcd.print ("Hr ");
}
else
{
lcd.print (time_run / 60000L);//msec
lcd.print ("Min ");
}
}
break;
default:
{
fonction = 2;
}
break;
}
///////////////////////////////////////////////////////
// eco mode
//
///////////////////////////////////////////////////////
if (eco_mode == true)
{
//char buffer[4]; //2del
gpsSerial.write(gpsSleep, sizeof(gpsSleep));
gpsSerial.flush();
for (int n = 0; n < 6 ; n++)//Sec.
{
lcd.setCursor(15, 0); lcd.print (n);
Print_Tide(6, 1);
delay (1500);
Print_wpazimut(6, 1);
delay (1500);
if (digitalRead(sw_sel) == 0)
{
lcd.clear ();
while (digitalRead(sw_sel) == 0) {}; delay(10); // debounce
menu(0);
}
}
gpsSerial.write(gpsHot, sizeof(gpsHot));
gpsSerial.flush();
delay (2000); //
//vinfo = 1;
}
}
}
}
}

///////////////////////////////////////////////////////
// MENU //
///////////////////////////////////////////////////////
static char* menu_items [] = {"Sel-UP-down", "Power OFF", "Lat-Long & WP ", "Power
Moniteur",
"Eco Mode", "GMT set ", "TIDE set" , "Display Mode", "Odometre", "Retour", "Sel-up-
DOWN"
};
void menu(int menu_index)
{
lcd.clear(); lcd.print(menu_items[menu_index]);
while (digitalRead(sw_sel) == LOW) {}; delay(5); //Debounce
while (digitalRead(sw_sel) != LOW)// Select
{
if (digitalRead(sw_up) == LOW)
{
lcd.clear();
while (digitalRead(sw_up) == LOW) {}; delay(10); //Debounce
menu_index ++;
if (menu_index > 8)
{
menu_index = 0;
}
lcd.clear();
//lcd.setCursor(0, 0); lcd.print(menu_items[0]);
lcd.setCursor(0, 1);
lcd.print(menu_items[menu_index]);
}
if (digitalRead(sw_dwn) == LOW)
{
lcd.clear();
while (digitalRead(sw_dwn) == LOW) {}; delay(10); //Debounce
menu_index -= 1;
if (menu_index < 0)
{
menu_index = 8;
}
lcd.clear();
lcd.print(menu_items[0]);
lcd.setCursor(0, 1);
lcd.print(menu_items[menu_index]);
}
}
lcd.clear();
while (digitalRead(sw_sel) == LOW) {}; delay(100); //Debounce
switch (menu_index)
{
case 1:
///////////////////////////////////////////////////////
// POWER OFF //
///////////////////////////////////////////////////////
{
lcd.clear();
lcd.print ("POWER OFF....");
delay (1500);
digitalWrite(power_pin, LOW);
delay (50);
asm volatile (" jmp 0");
}
break;
case 2:
///////////////////////////////////////////////////////
// LAT et LONG MEMO //
///////////////////////////////////////////////////////
{
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print("Push DWN to Save") ;
lcd.setCursor (0, 1);
lcd.print("WayPoint ") ;
delay (1000); lcd.clear ();
while (digitalRead(sw_sel) != LOW)
{
Print_Latitude (0, 0);
Print_Longitude (0, 1);
if (digitalRead(sw_dwn) == LOW)
{
wp_lat = lat;
wp_lon = lon;
EEPROM.put(10, lat);
EEPROM.put(15, lon);
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print("WayPoint SAVED") ;
delay (1500);
break;
}
if (digitalRead(sw_up) == LOW)
{
lcd.clear ();
lcd.setCursor (0, 0);
lcd.print("Push DWN to Save") ;
while (digitalRead(sw_up) == LOW) {};
delay(1000);
lcd.clear ();
}
gps.get_position(&lat, &lon);
lat = lat / 100; //enlever les d-secondes
lon = lon / 100;
}
lcd.clear ();
while (digitalRead(sw_sel) == LOW) {};
}
break;
case 3:
///////////////////////////////////////////////////////
// POWER MONITOR batt sol //
///////////////////////////////////////////////////////
{
gpsSerial.write(gpsSleep, sizeof(gpsSleep));
while (3)
{
float vsol = (float) analogRead(solPanel) / 204; // 1024/5voltsRef
dtostrf (vsol, 3, 1, msg) ;
lcd.setCursor(0, 0);
lcd.print ("Solaire=");
lcd.print (msg);
lcd.print ("V ");
float vbatt = (float) analogRead(batt) / vref + .21; // 1024/5voltsRef
dtostrf (vbatt, 3, 1, msg) ;
lcd.setCursor(0, 1);
lcd.print ("Batterie=");
lcd.print (msg); lcd.print ("V ");
if ((vsol - vbatt) > .4)//volts
{
lcd.setCursor(12, 1); lcd.print ("V Charge ");
}
else
{
lcd.setCursor(12, 1); lcd.print ("V ");
}
delay (1000);
if (digitalRead(sw_sel) == LOW)
{
lcd.clear();
while (digitalRead(sw_sel) == LOW) {} ;
gpsSerial.write(gpsHot, sizeof(gpsHot));
return;
}
delay (1000);
}
}
break;
case 4:
///////////////////////////////////////////////////////
/// ECO MODE select ///
///////////////////////////////////////////////////////
{
if (eco_mode == false)
{
lcd.setCursor(0, 0); lcd.print("ECONO MODE ON ");
delay (1500);
eco_mode = true;
analogWrite(LCD_LED, 0); // off lcd led
}
else
{
lcd.setCursor(0, 0); lcd.print("ECONO MODE OFF ");
eco_mode = false;
delay (1500);
analogWrite(LCD_LED, LCD_LED_N); // off lcd led
}
lcd.clear ();
}
break;
case 5:
///////////////////////////////////////////////////////
// GMT //
///////////////////////////////////////////////////////
{
//gmt = 0;
while (digitalRead(sw_sel) != LOW)
{
if (digitalRead(sw_up) == LOW)
{
lcd.clear ();
while (digitalRead(sw_up) == LOW) {} ;
gmt ++;
}
if (digitalRead(sw_dwn) == LOW)
{
lcd.clear ();
while (digitalRead(sw_dwn) == LOW) {} ;
gmt --;
}
lcd.clear();
lcd.print ("GMT");
lcd.print(gmt);
delay (300);
}
lcd.clear ();
while (digitalRead(sw_sel) == LOW) {} ;
lcd.setCursor (0, 1);
lcd.print ("SET GMT");
lcd.print(gmt);
EEPROM.write(0, gmt);
delay(1000);
return;
}
break;
case 6:
///////////////////////////////////////////////////////
// SET TIDE //
///////////////////////////////////////////////////////
{
//int tide_min, tide_hr;
lcd.setCursor (0, 0);
lcd.print ("Set ");
lcd.setCursor (0, 1);
lcd.print ("FullMoonHighTide");
EEPROM.get(20, Tide_one);
int tide_mth = 1;
//float a = (float)Tide_one / 288; //288 = 24hr * 60/ 5 min/hr)
int tide_jr = 12; //(int)a;
//float b = (a - (float) tide_jr) * 24;
int tide_hr = 7; // (int)b;
int tide_min = 45; //(b - (float) tide_hr) * 60 ;

///////////////////////////////////////////////////////
lcd.clear ();
while (digitalRead(sw_sel) != LOW)
{
lcd.setCursor (0, 1);
lcd.print (tide_mth); lcd.print("/");
lcd.setCursor (3, 1); lcd.print(tide_jr); lcd.print(" ");
lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" ");
lcd.setCursor (0, 0) ;
lcd.print("v--Month ");
delay (350);
if (digitalRead(sw_up) == LOW)
{
tide_mth ++;
}
if (digitalRead(sw_dwn) == LOW)
{
tide_mth --;
}
}
///////////////////////////////////////////////////////
lcd.clear ();
while (digitalRead(sw_sel) == LOW) {}; delay (100);
while (digitalRead(sw_sel) != LOW)
{
lcd.setCursor (0, 1);
lcd.print (tide_mth); lcd.print("/");
lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" ");
lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" ");
lcd.setCursor (3, 0);
delay (350);
lcd.print("v--Day ");
if (digitalRead(sw_up) == LOW)
{
tide_jr ++;
}
if (digitalRead(sw_dwn) == LOW)
{
tide_jr --;
}
}
///////////////////////////////////////////////////////

lcd.clear ();
while (digitalRead(sw_sel) == LOW) {}; delay (100);
while (digitalRead(sw_sel) != LOW)
{
lcd.setCursor (0, 1);
lcd.print (tide_mth); lcd.print("/");
lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" ");
lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" ");
lcd.setCursor (8, 0);
lcd.print("v--Hr ");
delay (350);
if (digitalRead(sw_up) == LOW)
{
tide_hr ++;
}
if (digitalRead(sw_dwn) == LOW)
{
tide_hr --;
}
}
///////////////////////////////////////////////////////
lcd.clear ();
while (digitalRead(sw_sel) == LOW) {}; delay (100);
while (digitalRead(sw_sel) != LOW)
{
lcd.setCursor (0, 1);
lcd.print (tide_mth); lcd.print("/");
lcd.setCursor (3, 1); lcd.print(tide_jr ); lcd.print(" ");
lcd.setCursor (8, 1); lcd.print(tide_hr); lcd.print(":"); lcd.print(tide_min); lcd.print(" ");
lcd.setCursor (5, 0);
lcd.print("Min--v ");
delay (350);
if (digitalRead(sw_up) == LOW)
{
tide_min += 5;
}
if (digitalRead(sw_dwn) == LOW)
{
tide_min -= 5;
}
if (tide_min < 1) {
tide_min = 1; // prevention 0/5
}
}
lcd.clear ();
while (digitalRead(sw_sel) == LOW) {}
Tide_one = DofY (year, tide_mth, tide_jr, tide_hr, tide_min);
lcd.setCursor (0, 0);
lcd.print ("Tide_one="); lcd.print (Tide_one); lcd.print (" ");
lcd.setCursor (0, 1);
lcd.print (tide_mth); lcd.print("/"); lcd.print (tide_jr ); lcd.print (" "); lcd.print (tide_hr);
lcd.print (":"); lcd.print (tide_min);
delay (3500);
while (digitalRead(sw_sel) == LOW) { }
lcd.clear ();
lcd.print ("Push Dwn to Save");
while (digitalRead(sw_sel) != LOW)
{
if (digitalRead(sw_dwn) == LOW)
{
if (Tide_one > 0)
{
EEPROM.put(20, Tide_one);
lcd.clear ();
lcd.print ("TIDE SAVED");
lcd.setCursor (0, 1);
lcd.print (Tide_one);
delay (2000);
while (digitalRead(sw_dwn) == LOW) { }
lcd.clear ();
return;
}
else
{
lcd.clear ();
lcd.print ("TIDE E R R O R");
lcd.setCursor (0, 1);
lcd.print (Tide_one);
delay (2500);
lcd.clear ();
return;
}
}
delay (50);
}
lcd.clear ();
return;
}
break;
case 7:
///////////////////////////////////////////////////////
// PRO MODE //
///////////////////////////////////////////////////////
{
if (pro_mode == false)
{
lcd.clear(); lcd.print("PRO Display ");
delay (1500);
pro_mode = true;
EEPROM.write(4, pro_mode);
}
else
{
lcd.clear(); lcd.print("Dashboard ");
pro_mode = false;
EEPROM.write(4, pro_mode);
delay (1500);
}
lcd.clear ();
}
break;
case 8:
///////////////////////////////////////////////////////
// ODOMETRE //
///////////////////////////////////////////////////////
{
Odometre = 0;
time_run = 0;
lat2 = lat;
lon2 = lon;
lcd.clear(); lcd.print("Odometre Reset");
delay (1500); lcd.clear ();
}
break;
default:
{
}
return;
}
}
/////////////////////////////////////////////////////////////////////////////////////
// SUBROUTINES //
/////////////////////////////////////////////////////////////////////////////////////
// writeBigChar: writes big character 'ch' to column x, row y; returns number of columns
used by 'ch'
int writeBigChar(char ch, byte x, byte y) {
if (ch < ' ' || ch > '_') return 0; // If outside table range, do nothing
nb = 0; // character byte counter
for (bc = 0; bc < 8; bc++) {
bb[bc] = pgm_read_byte( &bigChars[ch - ' '][bc] ); // read 8 bytes from PROGMEM
if (bb[bc] != 0) nb++;
}
bc = 0;
for (row = y; row < y + 2; row++) {
for (col = x; col < x + nb / 2; col++ ) {
lcd.setCursor(col, row); // move to position
lcd.write(bb[bc++]); // write byte and increment to next
}
}
return nb / 2 - 1; // returns number of columns used by char
}
// writeBigString: writes out each letter of string
void writeBigString(char *str, byte x, byte y)
{
char c;
while ((c = *str++))
x += writeBigChar(c, x, y) + 1;
}
///////////////////////////////////////////////////////
// HORLOGE //
///////////////////////////////////////////////////////
void horloge(int C, int R)
{
lcd.setCursor(C, R);
lcd.print(hour); lcd.print(":");
if (minute < 10)
{
lcd.print("0");
}
lcd.print(minute);
lcd.print(" ");
}
///////////////////////////////////////////////////////
// LATITUDE //
///////////////////////////////////////////////////////
void Print_Latitude(int C, int R)
{
long latdeg = (lat / 10000);
lcd.setCursor(C, R);
lcd.print("Lat:");
lcd.print(abs(latdeg));
lcd.print((char)223);
float x = (float)(lat - latdeg * 10000) * .6 / 100;
lcd.print(x); lcd.print("'");
if (lat > 0)
{
lcd.print ("N");
}
else
{
lcd.print("S");
}
}
///////////////////////////////////////////////////////
// PRINT LONGITUDE //
///////////////////////////////////////////////////////
void Print_Longitude(int C, int R)
{
long londeg = (lon / 10000);
lcd.setCursor(C, R);
lcd.print("Lon:");
lcd.print(abs(londeg));
lcd.print((char)223);
float x = (float) (abs(lon) - abs(londeg) * 10000) * .6 / 100;
lcd.print(x); lcd.print("'");
if (lon > 0) {
lcd.print("E");
}
else {
lcd.print("W");
}
}

///////////////////////////////////////////////////////
// TIDE CLOCK display //
///////////////////////////////////////////////////////
void Print_Tide(int C, int R)
{
EEPROM.get(20, Tide_one);
const char*tideclock [] {"HIGH ", "L 5Hr ", "L 4Hr ", "L 3Hr ", "L 2Hr ", "L 1Hr ",
"LOW ", "H 5Hr ", "H 4Hr ", "H 3Hr ", "H 2Hr ", "H 1Hr ", "HIGH ", "ERR "};
//Serial.print ("y min="); //Serial.println (Year_Min);
//Serial.print ("tide 1="); //Serial.println (Tide_one);
long tide_cycle = (Year_Min - Tide_one);
//Serial.print ("tide cycle="); //Serial.println (tide_cycle);
float tide_cyclef = (float)tide_cycle / 745.233333f; //Tide 12h25m14sec (745.23 min)
dtostrf (tide_cyclef, 1, 6, msg) ;
//Serial.print ("tide cyclef="); //Serial.println (msg);
tide_cyclef = tide_cyclef - int(tide_cyclef);
dtostrf (tide_cyclef, 1, 6, msg) ;
//Serial.print ("tide cyclefraction="); //Serial.println (msg);
tide_cyclef = tide_cyclef * 12;
dtostrf (tide_cyclef, 1, 6, msg) ;
tide_cycle = round (tide_cyclef);
lcd.setCursor(C, R);
lcd.print ("Tide:");
lcd.print (tideclock[tide_cycle]);
//; break;

62) Arduino Morse Code Machine


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Buzzer

× 1

LED (generic)

× 1
SparkFun Pushbutton switch
12mm
× 1

Jumper wires (generic)

× 10
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Although I am pretty new to the IoT and Arduino stage, with the help
of my friends and classmates and my professor I got into it pretty
quickly. This was one of my first real projects, finished a while ago,
but I am still making improvements.
Morse Code
Considering I knew Morse code as a kid, and that I wanted to play with
the components, I decided on the Morse machine.
The isn't to hard to make, it requires some basic parts (listed below)
and some basic programming skill (feel free to play with the code and
make it more interesting/efficient). Although writing in Morse code is
pretty hard you get a hang of it after a while. I practiced with printed
out sheet which you can get online. Don't feel bad if you make
mistakes or the timer feels odd, for practice I advise to change those
variable values to make it easier to practice and when you become a
pro, turn down those values, so you sound like a pro.

SCHEMATICS
CODE

const int buttonPin = 2;


const int ledPin = 13;
const int buzzer = 9;
int ledState = HIGH;
int buttonState = LOW;
int lastButtonState = LOW;
int doesitwork = LOW; // variable used for debuging early versions of the code

int pause_value = 250; // depending on your skill and how fast your fingers are you can
change this value to make typing a message faster or slower
long signal_length = 0;
long pause = 0;

String morse = "";


String dash = "-";
String dot = "*";

boolean cheker = false;


boolean linecheker = false;

long lastDebounceTime = 0;
long debounceDelay = 50;
void setup()
{
Serial.begin(9600);

pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(buzzer, OUTPUT);

Serial.println("Welcome to Arduino-Uno morse machine");


Serial.println("Using these values print out your message in morse and read out the
message in english in the serial monitor");
Serial.println("https://goo.gl/images/R4AIsW morse code values for learing");

while(!digitalRead(buttonPin))
;

void loop() {

buttonState = digitalRead(buttonPin);

if (buttonState && lastButtonState) // basic state machine depending on the state of the
signal from the button
{
++signal_length;
if (signal_length<2*pause_value) //this help to notice that there is a change in the
signal length aka that its not a dot anymore but a dash
{ // best use for the measuring of signal_length would be use of the
millis() but this was used for simplicity
tone(buzzer, 1500) ;
}
else
{
tone(buzzer, 1000) ;
}
}
else if(!buttonState && lastButtonState) //this part of the code happens when the
button is released and it send either * or - into the buffer
{

if (signal_length>50 && signal_length<2*pause_value )


{
morse = morse + dot;
}
else if (signal_length>2*pause_value)
{
morse = morse + dash;
}
signal_length=0;
digitalWrite(13, LOW);
noTone(buzzer);
}
else if(buttonState && !lastButtonState) // this part happens when the button is
pressed and its use to reset several values
{
pause=0;
digitalWrite(13, HIGH);
cheker = true;
linecheker = true;
}
else if (!buttonState && !lastButtonState)
{
++pause;
if (( pause>3*pause_value ) && (cheker))
{
printaj(morse);
cheker = false;
morse = "";
}
if ((pause>15*pause_value) && (linecheker))
{
Serial.println();
linecheker = false;
}
}
lastButtonState=buttonState;
delay(1);
}
void printaj(String prevodilac) //ugly part of the code but it works fine
{ //compare morse string to known morse values and print out the letter
or a number
//the code is written based on the international morse code, one thing i changed is that
insted of typing a special string to end the line it happens with enough delay
if (prevodilac=="*-")
Serial.print("A");
else if (prevodilac=="-***")
Serial.print("B");
else if (prevodilac=="-*-*")
Serial.print("C");
else if (prevodilac=="-**")
Serial.print("D");
else if (prevodilac=="*")
Serial.print("E");
else if (prevodilac=="**-*")
Serial.print("F");
else if (prevodilac=="--*")
Serial.print("G");
else if (prevodilac=="****")
Serial.print("H");
else if (prevodilac=="**")
Serial.print("I");
else if (prevodilac=="*---")
Serial.print("J");
else if (prevodilac=="-*-")
Serial.print("K");
else if (prevodilac=="*-**")
Serial.print("L");
else if (prevodilac=="--")
Serial.print("M");
else if (prevodilac=="-*")
Serial.print("N");
else if (prevodilac=="---")
Serial.print("O");
else if (prevodilac=="*--*")
Serial.print("P");
else if (prevodilac=="--*-")
Serial.print("Q");
else if (prevodilac=="*-*")
Serial.print("R");
else if (prevodilac=="***")
Serial.print("S");
else if (prevodilac=="-")
Serial.print("T");
else if (prevodilac=="**-")
Serial.print("U");
else if (prevodilac=="***-")
Serial.print("V");
else if (prevodilac=="*--")
Serial.print("W");
else if (prevodilac=="-**-")
Serial.print("X");
else if (prevodilac=="-*--")
Serial.print("Y");
else if (prevodilac=="--**")
Serial.print("Z");

else if (prevodilac=="*----")
Serial.print("1");
else if (prevodilac=="**---")
Serial.print("2");
else if (prevodilac=="***--")
Serial.print("3");
else if (prevodilac=="****-")
Serial.print("4");
else if (prevodilac=="*****")
Serial.print("5");
else if (prevodilac=="-****")
Serial.print("6");
else if (prevodilac=="--***")
Serial.print("7");
else if (prevodilac=="---**")
Serial.print("8");
else if (prevodilac=="----*")
Serial.print("9");
else if (prevodilac=="-----")
Serial.print("0");

Serial.print(" ");

prevodilac="";
}
63) Arduino Insteon Gateway
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Arduino Ethernet Rev. 3

× 1

Insteon PLM
× 1
Arduino wiring shield
× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1

Power supply 12v 2A


× 1

Plastic enclosure
× 1

ABOUT THIS PROJECT

The project is about Home Automation. I have some devices that are
Insteon-based. Insteon uses a proprietary protocol to make the devices
communicate wirelessly together, in a mesh topology.
Here are examples:
Dimmer Module,
On/off Module,
Dimmer Switch,
On/off Switch,
Dimmer Keypad (by 8 or by 6),
Thermostat,
Motion detector
The goal of this project is to build a gateway betwen Insteon world and
a generic MQTT broker, over IP BUT without dependency to Insteon
Cloud.
Features
Here are the features provided by the "Insteon gateway":
Gather and publish statuses: Arduino will (over a serial link to the
PLM ) get info published by all devices, display them on the front
panel, convert it to MQTT messages and send them to the MQTT
broker
Listen, push and execute commands: Arduino will listen to specific
MQTT queues (one per targeted Insteon device, display the
messages to the front panel and push those commands to the PLM
(over serial link). PLM will transfer those commands to the targeted
devices.
SCHEMATICS
CODE

#include <ArduinoJson.h>
#include <avr/wdt.h>
#include <Ethernet.h>
#include <LiquidCrystal.h>
#include <Network.h>
#include <PubSubClient.h>
#include <QueueArray.h>
#include "SoftwareSerial.h"
#include <SPI.h>
#include <Timer.h>

// HW pinout
const int LCD_E_PIN PROGMEM = 2; // LCD
const int RESET_BTN_PIN PROGMEM = 3; // goes to LOW
when someone press on the button and then goes to HIGH when button is released,
otherwise pull-down to GND
const int SD_CARD_PIN PROGMEM = 4; // SD card on
ethernet shield, not used
const int LCD_DB4_PIN PROGMEM = 5; // LCD
const int LCD_DB5_PIN PROGMEM = 6; // LCD
const int LCD_DB6_PIN PROGMEM = 7; // LCD
const int LCD_DB7_PIN PROGMEM = 8; // LCD
const int LCD_RS_PIN PROGMEM = 9; // LCD
const int INSTEON_TX PROGMEM = 16; // TX to INSTEON
PLM
const int INSTEON_RX PROGMEM = 17; // RX from
INSTEON PLM

// Network
const byte mac[] = { 0xDE, 0xED, 0xBE, 0xBB, 0xFC, 0xAC }; // Arduino's
MAC address
IPAddress ip(192, 168, 1, 221); // Arduino's IP address
IPAddress server(192, 168, 1, 100); // MQTT broker's address
(Orechestrator)
EthernetClient ethClient;

// MQTT
PubSubClient client(ethClient);
const int mqttInterval PROGMEM = 300; // determines how often
the system will report to MQTT broker (ie. every mqttInterval * mainLoopDelay ms )
int mqttIntervalCnt = 0; // local variable used to count
down
int isConnectedToBroker = -1; // 1 when connected, -1 =
unknown, 0 = unable to connected
#define INSTEONGATEWAY "PLM"

// Insteon
SoftwareSerial InsteonSerial(INSTEON_RX, INSTEON_TX, true); // This is
what we use to send/receive Insteon commands using the home automation shield
const int PLMtimeOut PROGMEM = 1000; // in millisec
int inByte[26]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // for storing
incoming serial bytes
int outByte[26]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // for storing
ougoing serial bytes
const int zeroByte PROGMEM= 0x00; // I use this because if I
do "Serial.write (0);" instead I get a compile error
const int startByte PROGMEM = 0x02; // Every Insteon message
begins with this
const int msgLength PROGMEM = 30; // Used to assign an
expected length for the message... starts out high so that we don't prematurely trigger an
end-of-message
int i = 0; // Looping variable for incoming
messages
int j = 0; // Looping variable for outgoing
messages

// Display and log


const int mode PROGMEM = 1; // 0 = normal, 1 = verbose
LiquidCrystal lcd (LCD_RS_PIN, LCD_E_PIN, LCD_DB4_PIN, LCD_DB5_PIN
,LCD_DB6_PIN, LCD_DB7_PIN);
const int LCD_ROWS = 2;
const int LCD_COLUMNS = 16;

// Local queue
volatile QueueArray <byte> cmdQueue; // each command received
from MQTT broker is stored here
byte* incoming; // an incoming message to route to
Insteon network

// Manual RESET button


volatile boolean isResetRequested = 0; // this one will change when
button triggers an interrupt

// Logic
const int mainLoopDelay = 500; // a fixed delay within main
loop, in ms
void(* resetFunc) (void) = 0;

// Initialization
void setup()
{
wdt_disable(); // disable watchdog
Serial.begin(19200); // open console port
Serial.println(F("Begin of setup"));
pinMode(SD_CARD_PIN, OUTPUT); // always good to disable it, if
it was left 'on' or you need init time
digitalWrite(SD_CARD_PIN, HIGH); // to disable SD card since we
do not use it
pinMode (RESET_BTN_PIN, INPUT);
InsteonSerial.begin(19200); // open another serial port for Insteon
PLM
cmdQueue.setPrinter (Serial); // setup local queue
lcd.begin(LCD_COLUMNS, LCD_ROWS); // set up the LCD's number
of columns and rows:
testLCD(); // just a welcome message
client.setServer(server, 1883); // setup MQTT
client.setCallback(MQTTBrokerCallback);
Ethernet.begin(mac, ip); // setup network
Serial.print(F("Current IP is : "));
Serial.print(Ethernet.localIP());
Serial.print(F(" - MQTT broker IP is : "));
Serial.println(server);
enableInterruptOnResetButton(); // from here, interrupts are trapped
subscribeToToDoLists(); // from here, callbacks are trapped
delay(1500); // allow hardware to sort itself out
Serial.println(F("End of setup")); Serial.println();
}

// Main loop

void loop()
{
if (isResetRequested == 1) {resetAll();} // someone pressed the Reset button
// Part 1 : deal with messages originating from Insteon PLM

while (InsteonSerial.available() > 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<26;j++) outByte[j] = 0xFF;
while (!cmdQueue.isEmpty ())
{
b = cmdQueue.dequeue();
if (b == ':') // delimiter between each set of 2 characters
{
hex = 0;
hex_digit_to_read = 2;
reading_hex = true;
continue;
};
if (hex_digit_to_read > 0)
{
hex = (hex << 4) | CharToHex(b);
hex_digit_to_read--;
};
if (reading_hex && hex_digit_to_read == 0)
{
reading_hex = false;
if (hex == 0x02) // end of message
{
hex_digit_to_read = 2;
reading_hex = true;
hex = 0;
j = 0;
return 0;
}
else
{
outByte[j] = hex;
Serial.print(hex, HEX);
Serial.print(' ');
j++;
};
};
};
}
// Send commands to Insteon devices

int sendMessageToInsteonDevice()
{
Serial.print(F("Sending command to Insteon devices : "));
sendCmd(2, false);
sendCmd(98, false);
sendCmd(outByte[1], true);
sendCmd(outByte[2], true);
sendCmd(outByte[3], true);
sendCmd(15, false);
sendCmd(outByte[4], false);
sendCmd(outByte[5], false);
Serial.println();
}

void sendCmd(byte b, bool isHex)


{
if (isHex) { Serial.print(b, HEX); } else { Serial.print(b); };
Serial.print(F("-"));
InsteonSerial.write(b);
}

// Gather bytes sent by Insteon PLM in order to get a well structured message

int receiveMessageFromPLM()
{
long start_time = millis();
int currentIndex = 0;
for(int j=0;j<26;j++) inByte[j] = 0;
byte currentByte;
while (true)
{
if ((millis() - start_time) > PLMtimeOut) // we should get a complete message in a short
period of time
{
displayError1();
return 1;
};
if (InsteonSerial.available() > 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<26;i++)
{
if ( outByte[i] == 0xFF) { break;}
Serial.print(InsteonSerial.write(outByte[i]));
}
}

// Reset button management

void resetAll()
{
Serial.println(F("Someone pushed on the button to reset this device"));
displayInfo("Reset requested");
routeGatewayStatusMessageToBroker();
wdt_enable(WDTO_1S); //enable watchdog, will fire in 1 second
delay(5000);
Serial.println(F("This message should never appear... unless this board is a zombie"));
}
void enableInterruptOnResetButton()
{
isResetRequested = 0;
attachInterrupt(1, onResetRequested, CHANGE);
}
void onResetRequested()
{
detachInterrupt(1);
isResetRequested = 1;
}

//
// MQTT related functions
//
// NOTE : MQTT_MAX_PACKET_SIZE = 128 bytes.. therefore not more than 100 for the
payload !!!!!!!
// unless you change it in /Arduino/libraries/pubSubClient/src/PubSubClient.h

// Route broadcasts to MQTT broker (topic = GLI/XX-YY-ZZ/WhishList)

void routeGroupBroadcastMessageToBroker()
{
char topic[30];
strcpy(topic, "GLI");
strcat(topic, "/");
strcat(topic, byteToHexaString(inByte[2]));
strcat(topic, "-");
strcat(topic, byteToHexaString(inByte[3]));
strcat(topic, "-");
strcat(topic, byteToHexaString(inByte[4]));
strcat(topic,"/");
strcat(topic, "WhishList");
char payload[100];
strcpy(payload, "{");
strcat(payload,"\n");
strcat(payload,"\"Group\": ");
strcat(payload, byteToString(inByte[7]));
strcat(payload, ",");
strcat(payload,"\n");
strcat(payload,"\"Command\": ");
strcat(payload, byteToHexaString(inByte[9]));
strcat(payload, ",");
strcat(payload,"\n");
strcat(payload,"\"Parameters\": ");
strcat(payload, byteToString(inByte[10]));
strcat(payload,"\n");
strcat(payload,"}");
publishMsg( topic, payload);
}

// Route gateway status to MQTT broker (topic = GLI/Gateway/Status)

void routeGatewayStatusMessageToBroker()
{
char topic[30];
strcpy(topic, "GLI");
strcat(topic, "/");
strcat(topic, "Gateway");
strcat(topic,"/");
strcat(topic, "Status");
char payload[100];
strcpy(payload, "{");
strcat(payload,"\n");
strcat(payload,"\"ManualReset\": ");
strcat(payload,"\n");
if (isResetRequested == 1) { strcat(payload, "Yes");} else {strcat(payload, "No");};
strcat(payload,"\n");
strcat(payload, ",");
strcat(payload,"\n");
strcat(payload,"\"LocalQueueLevel\": ");
// strcat(payload, intToString(cmdQueue.count));
strcat(payload,"}");
publishMsg( topic, payload);
}

// Subscribe to the MQTT broker to get list of commands to forward to Insteon devices
(topic = GLI/Gateway/ToDo)

void subscribeToToDoLists()
{
if (connectToBroker() == true)
{
char topic[50];
strcpy(topic, "GLI");
strcat(topic, "/");
strcat(topic, "Gateway");
strcat(topic,"/");
strcat(topic, "ToDo");
client.subscribe(topic); // otherwise subscriptions will growth forever..
if (client.subscribe(topic) == true)
{
isConnectedToBroker = 1;
Serial.print(F("Registred to MQTT broker as a subscriber for the following topic: "));
Serial.println(topic);
}
else
{
Serial.println(F("Not registred to MQTT broker as a subscriber"));
isConnectedToBroker = 0;
}
client.loop();
}
else
{
isConnectedToBroker = 0;
Serial.println(F("Cannot subscribe to any topic since connection to MQTT broker is not
established"));
}
}

// This function will be invoked by MQTT broker each time a message is added to
GLI/Gateway/ToDo queue

void MQTTBrokerCallback(char* subscribedTopic, byte* payload, unsigned int


msgLength)
{
Serial.print(F("New message received from MQTT broker. Topic = "));
Serial.print(subscribedTopic);
Serial.print(F(", Length = "));
Serial.println(msgLength);
cmdQueue.enqueue('0');
cmdQueue.enqueue('2');
for (int i=0;i<msgLength;i++)
{
cmdQueue.enqueue(payload[i]); // store msg in local Queue
}
Serial.println();
}

// Report to MQTT broker

void publishMsg(const char* topic, const char* payload)


{
if (connectToBroker() == true)
{
if (client.publish( topic, payload ) == true)
{
isConnectedToBroker = 1;
Serial.print(F("Message sent to MQTT broker using the following topic "));
Serial.println(topic);
}
else
{
Serial.print(F("Message NOT sent to MQTT broker using the following topic "));
Serial.println(topic);
isConnectedToBroker = 0;
}
client.loop();
}
}

// Manage connection with MQTT broker

int connectToBroker()
{
// Serial.println(F(""));
// Serial.print(F("Connecting to network and to MQTT Broker... "));
if (client.connect(INSTEONGATEWAY) == true)
{
// Serial.print(F("connected as "));
// Serial.println(INSTEONGATEWAY);
}
else
{
switch (client.state())
{
case -4:
Serial.println(F("MQTT_CONNECTION_TIMEOUT - the server didn't respond within the
keepalive time"));
break;
case -3:
Serial.println(F("MQTT_CONNECTION_LOST - the network connection was broken"));
break;
case -2:
Serial.println(F("MQTT_CONNECT_FAILED - the network connection failed"));
break;
case -1:
Serial.println(F("MQTT_DISCONNECTED - the client is disconnected cleanly"));
break;
case 0:
break;
case 1:
Serial.println(F("MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the
requested version of MQTT"));
break;
case 2:
Serial.println(F("MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client
identifier"));
break;
case 3:
Serial.println(F("MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the
connection"));
break;
case 4:
Serial.println(F("MQTT_CONNECT_BAD_CREDENTIALS - the username/password
were rejected"));
break;
case 5:
Serial.println(F("MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to
connect"));
break;
default:
Serial.print("failed, rc=");
Serial.println(client.state());
break;
}
}
return client.connected();
}

//
// LCD management
//

void displayInsteonGroupBroadcast()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print('G');
lcd.setCursor(2,0);
lcd.print(inByte[2], HEX);
lcd.print('-');
lcd.print(inByte[3], HEX);
lcd.print('-');
lcd.print(inByte[4], HEX);
lcd.setCursor(0,1);
lcd.print("CMD");
lcd.setCursor(5,1);
lcd.print(inByte[9], HEX);
lcd.setCursor(8,1);
lcd.print("TO ");
lcd.setCursor(11,1);
lcd.print(inByte[7]);
delay(1000);
}

void displayInsteonOutgoingGroupBroadcast( const char* cmd, const char* dest, const


char* parms )
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print('I');
lcd.setCursor(2,0);
lcd.print('MQTT BROKER');
lcd.print("CMD");
lcd.setCursor(5,1);
lcd.print(cmd);
lcd.setCursor(8,1);
lcd.print("TO ");
lcd.setCursor(11,1);
lcd.print(dest);
delay(1000);
}
void displayBrokerMessage()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print('X');
delay(500);
}
void displayError(const String& code, const String& message)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print('E');
lcd.setCursor(0,2);
lcd.print(code);
lcd.setCursor(0,1);
lcd.print(message);
delay(500);
}
void displayInfo(const String& info)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(info);
delay(500);
}
void testLCD()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Hello PHSA !");
delay(500);
}
void displayRawData(byte b)
{
if (mode == 1)
{
Serial.print(F("["));
Serial.print(b, HEX);
Serial.print(F("]"));
};
}
void displayError1()
{
if (mode == 1)
{
Serial.print(F("An error (type 1) has occured while parsing message from PLM :
communication has timed out"));
};
displayError("1","Parsing");
}
void displayError2(byte currentByte)
{
if (mode == 1)
{
Serial.print(F("An error (type 2) has occured while parsing message from PLM : ["));
Serial.print(currentByte, HEX);
Serial.println(F("] skipped since it does not start with 0x20 as per the standard"));
};
displayError("2","Structure");
}
// Utility functions

char* byteToHexaString(byte b)
{
char buff[4];
snprintf(buff, 4, "%02X", b);
return buff;
}

char* byteToString(byte b)
{
char buff[4];
snprintf(buff, 4, "%d", b);
return buff;
}

char* intToString(int i)
{
char buff[4];
snprintf(buff, 4, "%d", i);
return buff;
}

int doubleBytesToInt(byte high_byte, byte low_byte)


{
return high_byte * 256 + low_byte;
}

int StrToHex(char str[])


{
return (int) strtol(str, 0, 16);
}

byte CharToHex(char c)
{
byte out = 0;
if( c >= '0' && c <= '9'){
out = (byte)(c - '0');
}
else if ( c >= 'A' && c <= 'F'){
out = (byte) (c - 'A') + 10;
}
else if ( c >= 'a' && c <= 'f'){
out = (byte) (c - 'a') + 10;
}

return out;
}

64) Arduino Monitorning the Fill Height of Paper Shredder


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

PHPoC Shield for Arduino

× 1

Ultrasonic Sensor - HC-SR04


× 1
Jumper wires (generic)

ABOUT THIS PROJECT

ntroduction
In this tutorial, I am going to show you how to detect the fullness of
a paper shredder and send a notification via Gmail using Arduino Uno.
I made this tutorial for beginners! It is really easy!

Detecting the Fill Height of Paper Shredder


Ultrasonic Sensor - HC-SR04 is used to detect the fullness of paper
shredder. When the distance between sensor and paper trash is at a
threshold, paper shredder is considered to be full.
Handling Event
In this project, when an event occurs, a notification is sent via Gmail.
SCHEMATICS

Assembly
Assembly
1. Stack PHPoC Shield on Arduino
2. Connect LAN cable or USB wifi Dongle to the shield for Ethernet
3. Pin wiring between Arduino and Sensor.

Pin wiring between Arduino and Sensor


All system
CODE

#define PIN_TRIG 5
#define PIN_ECHO 6
#define BIN_HEIGHT 20 // maximum containable height of bin in centimeters

#include "SPI.h"
#include "Phpoc.h"

long ultrasonicGetDistance();
boolean dustbinSendGmail();

PhpocEmail email;
boolean isSent = false;

void setup() {
Serial.begin(9600);
while(!Serial)
;
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);

Phpoc.begin(PF_LOG_SPI | PF_LOG_NET | PF_LOG_APP);

void loop() {
long distance = 0;
// read 10 time and get average value to eliminate noises
for(int i = 0; i < 100; i++)
{
long temp = 0;
do
{
temp = ultrasonicGetDistance();
}
while(temp > BIN_HEIGHT);

distance += temp;
delay(10);
}
distance /= 100;

Serial.print(distance);
Serial.println(" cm");

if(distance <= 5)
{
if(!isSent)
{
Serial.println("Dustbin is almost full");
isSent = dustbinSendGmail();
}
}
else if(isSent && distance > 8) // avoid send alot of email when the distance is oscillated
around 5cm
isSent = false;

delay(500);
}

long ultrasonicGetDistance(){
long duration, distance;
digitalWrite(PIN_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
duration = pulseIn(PIN_ECHO, HIGH);
distance = (duration/2) / 29.1;
return distance;
}

boolean dustbinSendGmail(){
// setup outgoing relay server - gmail.com
email.setOutgoingServer("smtp.gmail.com", 587);
email.setOutgoingLogin("your_login_id", "your_login_password");

// setup From/To/Subject
email.setFrom("from_email_address", "from_user_name");
email.setTo("to_email_address", "to_user_name");

email.setSubject("Your dustbin is almost full");

// write email message


email.beginMessage();
email.println("Location: Planet Earth.");
email.println("");
email.println("Your dustbin is almost full.");
email.println("");
email.println("Prepare to through it out.");

email.endMessage();

// send email
if(email.send() > 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

General Purpose Transistor NPN


I used 2N3904
× 4
Resistor 100 ohm

× 7

Resistor 10k ohm

× 4

One Channel Relay Module Board


Shield × 1
Relay
Adafruit 4 Digit 7 Segment LED
Display, 1.2" Yellow, Common
Cathode
Just a standard relay from × 1
Amazon\Ebay, +5V signal with
open connection when there is no
signal
Adafruit Powerboost 500C
× 1

Battery, 3.7 V
LiPo Battery 18650, 3000mAH
× 1
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 DC-


DC 3-40V to 1.25-35V × 1

Mini-360 step down converter DC-


DC 4.75V-23V to 1V-17V × 1

DHT11 Temperature & Humidity


Sensor (4 pins)
× 1

Carbon Monoxide (CO) Sensor -


MQ-7 × 1

Espressif ESP8266 ESP-12E

× 1

SparkFun Logic Level Converter -


Bi-Directional
× 1

5V Low Level Trigger 1 Channel


Relay Module × 1

SparkFun Pushbutton switch 12mm


× 1

Basic On/Off DC Switch


× 1

LED (generic)

× 6

Buzzer

× 1

USB-A to Micro-USB Cable

× 1

1N4007 – High Voltage, High


Current Rated Diode
× 2

Resistor 10k ohm

× 3

Jumper wires (generic)

× 1
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-stragety-
experments-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-arduino-
lesson-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<stdlib.h>
#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 <module online>...");
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

Buzzer

× 1

Rotary potentiometer (generic)

× 1

8x8 led matrix


× 1
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 <= 7) {
jugador.x = value;
}
return;
}

void asteroidFall() {
asteroid.y++;
//Serial.print("AsteroidY: ");
//Serial.print(asteroid.y);
//Serial.print("\n");
return;
}

void clearScreen() {
for (int led = 0; led < 8; led++)
{
digitalWrite(col[led], HIGH);
digitalWrite(row[led], LOW);
}
return;
}

int Update() {
if(updatedAsteroid == true && updatedPlayer == false) {
digitalWrite(col[jugador.x], LOW);
digitalWrite(row[jugador.y], HIGH);
updatedAsteroid = false;
updatedPlayer = true;
//Serial.print("Jugador Actualizado!!\n");
return 0; //retorna que se ha actualizado el jugador
} else {
digitalWrite(col[asteroid.x], LOW);
digitalWrite(row[asteroid.y], HIGH);
updatedAsteroid = true;
updatedPlayer = false;
//Serial.print("Asteroid Actualizado!!\n");
return 1; //retorna que se ha actualizado el asteroide
}
}

void puntuacion() {
if(asteroid.y == jugador.y && asteroid.x == jugador.x) {
digitalWrite(speakerPin, HIGH);
puntos++;
delay(100);
digitalWrite(speakerPin, LOW);
vidas += 2;
if(speed > 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

DFRobot pH Sensor DFRobot


× 1

SparkFun Bluetooth Modem -


BlueSMiRF Silver
× 1
Jumper wires (generic)

× 1

Temperature Sensor

× 1

9V to Barrel Jack Connector

× 1

9V battery (generic)

× 1

NXP Hexiwear

× 1
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 <SoftwareSerial.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define SensorPin A0 //pH meter Analog output to Arduino Analog


Input 0
#define Offset 0.00 //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 // Data wire is plugged into port 2


on the Arduino

OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to


communicate with any OneWire
//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"); //At command ERROR CODE for
Failed Executing statement
}else
if(find(message,"getT")){
float temp = 0;
sensors.requestTemperatures(); // Send the command to get
temperatures
temp = sensors.getTempCByIndex(0);
sensors.requestTemperatures(); // Send the command to get
temperatures
temp = sensors.getTempCByIndex(0);
if(temp==85)
sendData("\nTE1001"); //Temperature ERROR CODE for
INITIALIZE
else if(temp==0 || temp==-127)
sendData("\nTE1002"); //Temperature ERROR CODE for NOT
CONNECTED
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<=0){
Serial.println("Error number for the array to avraging!/n");
return 0;
}
if(number<5){ //less than 5, calculated directly statistics
for(i=0;i<number;i++){
amount+=arr[i];
}
avg = amount/number;
return avg;
}else{
if(arr[0]<arr[1]){
min = arr[0];max=arr[1];
}
else{
min=arr[1];max=arr[0];
}
for(i=2;i<number;i++){
if(arr[i]<min){
amount+=min; //arr<min
min=arr[i];
}else {
if(arr[i]>max){
amount+=max; //arr>max
max=arr[i];
}else{
amount+=arr[i]; //min<=arr<=max
}
}//if
}//for
avg = (double)amount/(number-2);
}//if
return avg;
}

/*
* Name: sendData
* Description: Function used to send string to tcp client using cipsend
* Params:
* Returns: void
*/
void sendData(String str){
String len="";
len+=str.length();
sendTobluetooth("AT+CIPSEND=0,"+len,responseTime,DEBUG);
delay(100);
sendTobluetooth(str,responseTime,DEBUG);
delay(100);
sendTobluetooth("AT+CIPCLOSE=5",responseTime,DEBUG);
}

/*
* Name: find
* Description: Function used to match two string
* Params:
* Returns: true if match else false
*/
boolean find(String string, String value){
if(string.indexOf(value)>=0)
return true;
return false;
}

/*
* Name: readSerialMessage
* Description: Function used to read data from Arduino Serial.
* Params:
* Returns: The response from the Arduino (if there is a reponse)
*/
String readSerialMessage(){
char value[100];
int index_count =0;
while(Serial.available()>0){
value[index_count]=Serial.read();
index_count++;
value[index_count] = '\0'; // Null terminate the string
}
String str(value);
str.trim();
return str;
}

/*
* Name: readbluetoothSerialMessage
* Description: Function used to read data from debugBluetooth Serial.
* Params:
* Returns: The response from the debugBluetooth (if there is a reponse)
*/
String readbluetoothSerialMessage(){
char value[100];
int index_count =0;
while(bluetoothSerial.available()>0){
value[index_count]=bluetoothSerial.read();
index_count++;
value[index_count] = '\0'; // Null terminate the string
}
String str(value);
str.trim();
return str;
}

/*
* Name: sendTobluetooth
* Description: Function used to send data to debugBluetooth.
* Params: command - the data/command to send; timeout - the time to
wait for a response; debug - print to Serial window?(true = yes, false = no)
* Returns: The response from the debugBluetooth (if there is a reponse)
*/
String sendTobluetooth(String command, const int timeout, boolean
debug){
String response = "";
bluetoothSerial.println(command); // send the read character to the
debugBluetooth
long int time = millis();
while( (time+timeout) > millis())
{
while(bluetoothSerial.available())
{
// The esp has data so display its output to the serial window
char c = bluetoothSerial.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.println(response);
}
return response;
}

/*
* Name: sendTobluetooth
* Description: Function used to send data to debugBluetooth.
* Params: command - the data/command to send; timeout - the time to
wait for a response; debug - print to Serial window?(true = yes, false = no)
* Returns: The response from the debugBluetooth (if there is a reponse)
*/
String sendToUno(String command, const int timeout, boolean debug){
String response = "";
Serial.println(command); // send the read character to the debugBluetooth
long int time = millis();
while( (time+timeout) > millis())
{
while(Serial.available())
{
// The esp has data so display its output to the serial window
char c = Serial.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Serial.println(response);
}
return response;
}

69) Arduino Water Level Monitor


COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

Resistor 1k ohm

× 1
5 mm LED: Green

× 1

Solu SL067 Water Sensor


× 1

USB-A to Mini-B Cable


× 1

5 V DC, 500 mA Power Supply


× 1

Small Guage Wire for DC


Applications. × 1

Heat Shrink Tubing, Assorted Sizes


× 1

Pocket Solder- 60/40 Rosin Core


0.031" diameter
× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Heat Gun
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


This project will demonstrate how to build a water level monitor using
an Arduino Nano, a Solu SL067 water level sensor, and an LED
indicator. There are many possible uses for this simple system,
examples include monitoring a sump pit (to control pump activation),
rainfall detection, leakage detection, or monitoring plant water levels. I
built this specifically to monitor the water level of my Christmas tree.
Credit:

I have significantly modified the code from the link above to use one
LED with blink codes rather than the three LEDs that were used in the
original development. I've also cleaned up the calibration instructions
to hopefully make this completely understandable for a layman. You
can simply assemble the circuit, upload my sketch to your Arduino, and
follow the calibration requirements to have a functional and reliable
water level monitor. Minimal programming knowledge is needed to
modify my sketch to suit your needs.
**NOTE - I have only been using this for a few days, and do not know
how well the sensor will hold up. There is potential for corrosion, and
it's possible that a piece of debris (wet pine needle) could short two
traces and give a false reading. I strongly recommend that you visually
confirm your water level until you are confident that the sensor will
continue to work as desired. I will continue to verify sensor operation
every few days, but this helps to avoid the necessity to move gifts and
tree skirt every day to check the water level.
About the sensor:
The sensor works by using a series of five exposed traces which are
connected to system ground. Interlaced between every two ground
trace is a sense trace, five ground traces and five sense traces in total.
The sense traces are connected to a 1 Megaohm pull-up resistor. The
sense traces are pulled high until a drop or plane of water shorts the
sense trace to ground. This sensor will theoretically output an analog
signal between 0-1024, but with the length of traces on this PCB I
found a usable range between 480 and ~710. The sensor is not designed
to be fully submersed, be mindful to install it so that only the exposed
traces on the PCB will be exposed to contact with water. Output
voltage of the sensor is 0 - 4.2 V, so this could be used as a digital input
if only low/high indication is required.
The analog output values correspond to the following distance from
bottom of the sensor (approximate):
480 = 0 mm
530 = 5 mm
615 = 10 mm
660 = 15 mm
680 = 20 mm
690 = 25 mm
700 = 30 mm
705 = 35 mm
710 = 40 mm
The sensor resolution decreases as the the water level increases.
== Installation
1. Upload the sketch to your Arduino.
2. Assemble the circuit using the schematic included with this project.
**LED: The LED resistor must be installed between the circuit ground
and LED. If your LED has one leg that is longer than the other, the
longer leg needs to be connected to the supply voltage (D2 of Arduino).
*Note: I used ~2.5 ft wire length for the sensor and 2 ft wire length for
the LED. This allowed me to place the Arduino away from the water,
and route the LED to the end of a tree branch for visibility.
3. Follow the calibration instructions below (also included in the
sketch):
**************************** Calibration/Setup
****************************
a) Connect Arduino to IDE and open serial monitor.
b) Insert depth sensor into water to a depth that you consider to be the
minimum amount needed to trigger the full indicator. Note the value
indicated in the serial monitor for use as the FULL level.
* Any value >= this will trigger the corresponding FULL blink code.
c) Repeat step 2 to determine the value you will assign to the LOW
value.
* Any value above this but below the FULL value will trigger the
corresponding INTERMEDIATE blink code.
* Any value below this value will trigger the corresponding LOW blink
code.
d) Plug the values determined from steps 2 and 3 in as the const int
FULL and LOW values in the sketch.
e) Upload the sketch with the updated values and your sensor is now
calibrated.
4. Place your Arduino is some type of enclosure to prevent damage
from water, moving parts, or shorts.
5. Install the system into your application.
=== Folder Structure
WaterLevelMontior_SingleLED => Arduino sketch folder
├── WaterLevelMonitor_SingleLED.ino => main Arduino file
├── WaterLevelMonitor.png => an image of the required schematics
└── ReadMe.adoc => this file
SCHEMATICS
CODE

roject: Water Level Monitor

****************************** Calibration/Setup
******************************
1) Upload sketch to Arduino and open serial monitor.
2) Insert depth sensor into water to a depth that you consider to be the
minimum amount needed
to trigger the full indicator. Note the value indicated in the serial monitor
for use as the FULL level.
* Any value >= this will trigger the corresponding FULL indicator.
3) Repeat step 2 to determine the value you will assign to the LOW value.
* Any value above this but below the FULL value will trigger the
corresponding INTERMEDIATE
blink code.
* Any value below this value will trigger the corresponding LOW blink
code.
4) Plug the values determined from steps 2 and 3 in as the const int FULL
and LOW values
in the sketch.
5) Upload the sketch with the updated values and your sensor is now
calibrated.
*/

const int full = 575;


const int low = 490;
int depthSensor = 0; //Set depthSensor input pin to Analog 0.
int lastValue = 0;
char printBuffer[128];

/* The following line sets the LED pin to the corresponding digital pin of
the
Arduino. You can set these to any digital pin as needed
*/

const int whiteLED = 2;

void setup()
{
Serial.begin(9600); // Begin serial communication to obtain sensor values
during calibration.
pinMode(whiteLED, OUTPUT); // Set LED pin to OUTPUT mode.
}

void loop()
{
int value = analogRead(depthSensor); // Read the sensor values.
if(((lastValue >= value) && ((lastValue - value) > 10)) || (lastValue = 10))
/* If the delta
between last and current value is > 10, display the current value. */
{
// Displays depth sensor value to serial port.
sprintf(printBuffer, "ADC%d level is %d\n", depthSensor, value);
Serial.print(printBuffer);
Serial.println();
//Serial.println(value);
//Serial.println();
// Set last value to current value for next loop.
lastValue - value;
}
if(value >= full)
{
// FULL
for(int x = 0; x < 3; x++){
digitalWrite(whiteLED, HIGH);
delay(800);
digitalWrite(whiteLED, LOW);
delay(800);
}
}
else if((value < full) && (value >= low))
{
// INTERMEDIATE
for(int x = 0; x < 2; x++){
digitalWrite(whiteLED, HIGH);
delay(1000);
}
}
else
{
//LOW
for(int x = 0; x < 4; x++){
digitalWrite(whiteLED, HIGH);
delay(100);
digitalWrite(whiteLED, LOW);
delay(100);
}
}
delay(3000); // Read current sensor value every three seconds.
}

/*
=== License
This project utilizes common electronic theory and C/C++ programming
language. I am not claiming to hold
a copyright or own any intellectual property related to the documents
included in this project. This
sketch, the associated ReadMe.adoc, and system schematic may be
modified or distributed freely. This
project is released under a Public Domain License.

=== DISCLAIMER
This SOFTWARE PRODUCT is provided by THE PROVIDER "as is"
and "with all faults." THE PROVIDER makes no
representations or warranties of any kind concerning the safety, suitability,
lack of viruses,
inaccuracies, typographical errors, or other harmful components of this
SOFTWARE PRODUCT. There are
inherent dangers in the use of any software, and you are solely responsible
for determining whether this
SOFTWARE PRODUCT is compatible with your equipment and other
software installed on your equipment. You
are also solely responsible for the protection of your equipment and
backup of your data, and THE
PROVIDER will not be liable for any damages you may suffer in
connection with using, modifying, or
distributing this SOFTWARE PRODUCT.
*/
70) Arduino Obstacles Avoiding Robot with Servo Motor
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

SG90 Micro-servo motor

× 1
SparkFun Ultrasonic Sensor - HC-
SR04 × 1

Robot Chassis Kit - 2WD with DC


Motors × 1

Jumper wires (generic)

× 1

Arduino MotorShield Rev3

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Step 1:
Prepare and build your Robot chasis. Inside the package have a few
components, chassis, two motors, two wheels, a front wheel, a battery
holder, some screws, switch and jumper wires. Photo below:

The instructions paper will come with the package that you buy from
online or the shops. Or else you can view "how to build" in the
youtube.
Step 2:
Before solder the jumper wires on your both motor, I would
recommend to test every components for make sure they all are
working well, example: Both DC motors, Arduino board, Motor Shield,
Servo motor and Ultrasonic sensor. Then we will start solder the red
and black wire on both motors, example picture below:

Step 3:
Come to our battery chassis and switch part. We only need to cut half
of the black wire from the battery chassis and solder 1 wire side at 1
hole, another black wire will solder at another hole. Our switch is
ready!
Step 4:
We will need to stack Arduino board and Motor Shield board, Motor
Shield will stack on Arduino board. Example below:
Step 5:
We will move on to the Motor Shield board. This shield provides power
to the motors and the servo motor, the motors need a lot of current, and
this shield can provide up to 600mA of current to each motor. We need
to solder/fixed the DC motors wires at the Motor shield board. If the
your DC motor wires are long enough to reach the Motor Shield will be
great, if not you might need to use external jumper wires(No matter is
Male/Female jumper wire), cut off the jumper wire head and make sure
inside the copper line shows up. (You will need to cut jumper wire
rubber to make the copper wire appear). And you need to solder the
external wires to the DC motor wires. Example:
Then connect the left motor wire to M1 connector of the motor shield.
Right motor wire will coneect to M3 connector from the Motor shield
board. Example:
Pictures by Darwin
Step 6:
Then we will need to connect the battery switch wires both red and
black wire to the Motor shield board.
For Battery switch wire (Pictures by Darwin)
After that, we will need to ready Male and Female jumper wires for
solder them to 5V, GND, Analog Pin 4 and Analog Pin 5. Before that,
we will need to find same colors of female and male jumper wires and
cut them into half. Why must be same color? First is easy for us to
recognize which wire are for which part. Second, white Male jumper
wire will solder with white Female jumper wire which connect to 5V.
Black color Male jumper wire will solder with female jumper wire and
Male jumper wire will solder to GND. Orange color Male jumper wire
will solder with orange Female jumper wire, Orange male jumper wire
will solder at Analog Pin 5. Lastly but not least, brown male jumper
wire will solder with female brown jumper wire, then brown color male
jumper wire will solder to Analog Pin 4. Example:
Pictures by Darwin
Step 7:
You are able to use double sided tape or hot glue gun for attach the
both shield on the robot chassis.
Step 8: Come to Ultrasonic Sensor part
From the Female & Male jumper wires that we solder just now, White
jumper wire(5V)(Female site jumper wire) will connect to Ultrasonic
Sensor VCC pin. Black Jumper wire(GND)(Female site jumper wire)
will connect to GND pin. Brown jumper wire(Analog Pin 4)(Female
site jumper wire) will connect to Echo pin. Orange color jumper
wire(Analog Pin 5)(Female site jumper wire) will connect to TRIG pin.
Step 9:
Lastly, For the Servo motor will connect to servo_2 slot. Note* (There
are few types of servo motor out there. you might need to find it online
for how they plug to servo_2 slot). Below is for my own version of
servo slot.

Last Step: Code


For this Obstacles avoiding robot, we will need 3 libraries, which is
Motor Shield library for Motor Shield driver

SCHEMATICS
CODE

#include <AFMotor.h>
#include <Servo.h>
#include <NewPing.h>

#define TRIG_PIN A4
#define ECHO_PIN A5
#define MAX_DISTANCE_POSSIBLE 1000
#define MAX_SPEED 150 //
#define MOTORS_CALIBRATION_OFFSET 3
#define COLL_DIST 20
#define TURN_DIST COLL_DIST+10
NewPing sonar(TRIG_PIN, ECHO_PIN,
MAX_DISTANCE_POSSIBLE);

AF_DCMotor leftMotor(3, MOTOR12_8KHZ);


AF_DCMotor rightMotor(1, MOTOR12_8KHZ);
Servo neckControllerServoMotor;

int pos = 0;
int maxDist = 0;
int maxAngle = 0;
int maxRight = 0;
int maxLeft = 0;
int maxFront = 0;
int course = 0;
int curDist = 0;
String motorSet = "";
int speedSet = 0;

void setup() {
neckControllerServoMotor.attach(10);
neckControllerServoMotor.write(90);
delay(2000);
checkPath();
motorSet = "FORWARD";
neckControllerServoMotor.write(90);
moveForward();
}
void loop() {
checkForward();
checkPath();
}

void checkPath() {
int curLeft = 0;
int curFront = 0;
int curRight = 0;
int curDist = 0;
neckControllerServoMotor.write(144);
delay(120);
for(pos = 144; pos >= 36; pos-=18)
{
neckControllerServoMotor.write(pos);
delay(90);
checkForward();
curDist = readPing();
if (curDist < COLL_DIST) {
checkCourse();
break;
}
if (curDist < TURN_DIST) {
changePath();
}
if (curDist > curDist) {maxAngle = pos;}
if (pos > 90 && curDist > curLeft) { curLeft = curDist;}
if (pos == 90 && curDist > curFront) {curFront = curDist;}
if (pos < 90 && curDist > curRight) {curRight = curDist;}
}
maxLeft = curLeft;
maxRight = curRight;
maxFront = curFront;
}

void setCourse() {
if (maxAngle < 90) {turnRight();}
if (maxAngle > 90) {turnLeft();}
maxLeft = 0;
maxRight = 0;
maxFront = 0;
}

void checkCourse() {
moveBackward();
delay(500);
moveStop();
setCourse();
}

void changePath() {
if (pos < 90) {lookLeft();}
if (pos > 90) {lookRight();}
}

int readPing() {
delay(70);
unsigned int uS = sonar.ping();
int cm = uS/US_ROUNDTRIP_CM;
return cm;
}

void checkForward() { if (motorSet=="FORWARD")


{leftMotor.run(FORWARD); rightMotor.run(FORWARD); } }

void checkBackward() { if (motorSet=="BACKWARD")


{leftMotor.run(BACKWARD); rightMotor.run(BACKWARD); } }

void moveStop() {leftMotor.run(RELEASE);


rightMotor.run(RELEASE);}

void moveForward() {
motorSet = "FORWARD";
leftMotor.run(FORWARD);
rightMotor.run(FORWARD);
for (speedSet = 0; speedSet < MAX_SPEED; speedSet +=2)
{
leftMotor.setSpeed(speedSet+MOTORS_CALIBRATION_OFFSET);
rightMotor.setSpeed(speedSet);
delay(5);
}
}

void moveBackward() {
motorSet = "BACKWARD";
leftMotor.run(BACKWARD);
rightMotor.run(BACKWARD);
for (speedSet = 0; speedSet < MAX_SPEED; speedSet +=2)
{
leftMotor.setSpeed(speedSet+MOTORS_CALIBRATION_OFFSET);
rightMotor.setSpeed(speedSet);
delay(5);
}
}

void turnRight() {
motorSet = "RIGHT";
leftMotor.run(FORWARD);
rightMotor.run(BACKWARD);
delay(400);
motorSet = "FORWARD";
leftMotor.run(FORWARD);
rightMotor.run(FORWARD);
}
void turnLeft() {
motorSet = "LEFT";
leftMotor.run(BACKWARD);
rightMotor.run(FORWARD);
delay(400);
motorSet = "FORWARD";
leftMotor.run(FORWARD);
rightMotor.run(FORWARD);
}

void lookRight() {rightMotor.run(BACKWARD); delay(400);


rightMotor.run(FORWARD);}
void lookLeft() {leftMotor.run(BACKWARD); delay(400);
leftMotor.run(FORWARD);}
71) Arduino Morse Encoder Displayer
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Breadboard (generic)

× 1
Jumper wires (generic)

× 27

Adafruit Standard LCD - 16x2


White on Blue
× 1

Buzzer

× 1

Resistor 221 ohm

× 1

Rotary potentiometer (generic)

× 2
APPS AND ONLINE SERVICES
Arduino IDE

Arduino Web Editor

ABOUT THIS PROJECT


This project is an Arduino program, that listen to the serial port
(reception/emission) and outputs two things:
Firstly, it convert the text you sent it into morse, and emit it via pin
11 (you may want to connect to a potentiometer in serie with a
buzzer).
Secondly, in the same time, on the LCD screen, it writes the letter it
is encoding and prints the morse code on the second line. When it
reaches the end of the first line, it clears the line.
It also send back what it received, prefixed with "Received: ".
When it does not recognize a character, it buzzes the length of 4 dots
then wait the equivalent of 2 dots, send an error message with the
character it didn't recognized and its binary value on the serial, and
replace the character with a "?" on the LCD screen.
I have an idea to upgrade this project: add a third potentiometer to
control the duration of a dot/dash/pauses.
SCHEMATICS

CODE
#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

#define BUZZER 11

#define SMALLER_DELAY 128

PROGMEM const uint8_t morse_code_a_z[26] = {


0b01100000, // A .-
0b10010101, // B -...
0b10011001, // C -.-.
0b10010100, // D -..
0b01000000, // E .
0b01011001, // F ..-.
0b10100100, // G --.
0b01010101, // H ....
0b01010000, // I ..
0b01101010, // J .---
0b10011000, // K -.-
0b01100101, // L .-..
0b10100000, // M --
0b10010000, // N -.
0b10101000, // O ---
0b01101001, // P .--.
0b10100110, // Q --.-
0b01100100, // R .-.
0b01010100, // S ...
0b10000000, // T -
0b01011000, // U ..-
0b01010110, // V ...-
0b01101000, // W .--
0b10010110, // X -..-
0b10011010, // Y -.--
0b10100101, // Z --..
};

void send_bit(const bool& dash) {


lcd.print(dash ? '-' : '.');
analogWrite(BUZZER, 63);
delay((dash ? 3 : 1) * SMALLER_DELAY);
digitalWrite(BUZZER, LOW);
delay(1 * SMALLER_DELAY);
}

uint8_t hpos = 0;
void send_char(const char& c) {
// Send the character to the LCD
lcd.setCursor(hpos++, 0);
lcd.print(c);

// Position the cursor to the next line to start the .- sequence


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

void print_number(const char& number) {


if (!isDigit(number)) return;

send_char(number);

uint8_t num = number - '0';


for (uint8_t i = 0 ; i < 5 ; i++) {
if (num == i) num += 10;

if (num < 6 + i) send_bit(false);


else send_bit(true);
}
}

void print_character(char character) {


if (!isAlpha(character)) return;

if (isLowerCase(character)) character += 'A' - 'a';

send_char(character);

uint8_t code = morse_code_a_z[character - 'A'];


while (code != 0) {
switch (code >> 6) {
case 0:
break;
case 1:
send_bit(false);
break;
case 2:
send_bit(true);
break;
case 3:
Serial.print("Error while printing character: ");
Serial.println(character);
Serial.print("Got 3 in the 2 leftmost bits of code ");
Serial.println(code, BIN);
break;
default:
Serial.print("Error while printing character: ");
Serial.println(character);
Serial.print("Got ? in the 2 leftmost bits of code ");
Serial.println(code, BIN);
}
code <<= 2;
}
}

void print_whitespace() {
send_char(' ');
delay(3 * SMALLER_DELAY);
}

void print_char(const char& character) {


if (isWhitespace(character)) print_whitespace();
else if (isAlpha(character)) print_character(character);
else if (isDigit(character)) print_number(character);
else if (isPunct(character)) { send_char(character); delay(1 * SMALLER_DELAY); }
else if (character == '\0') {}
else if (character == '\1') { /* This happens at the end of every string, don't know why */ }
else {
Serial.print("Error: unknown character ");
Serial.print(character);
Serial.print(" (0b");
Serial.print((uint8_t)character, BIN);
Serial.println(")");
send_char('?');
analogWrite(BUZZER, 63);
delay(4 * SMALLER_DELAY);
digitalWrite(BUZZER, LOW);
delay(1 * SMALLER_DELAY);
}

delay(2 * SMALLER_DELAY);
}

void print_string(const char* characters, int len = 15) {


for (uint8_t pos = 0 ; pos <= len ; pos++) {
print_char(characters[pos]);
}
}

void reset_LCD() {
hpos = 0;

lcd.clear();
lcd.noCursor();
lcd.setCursor(0, 0);
}

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);

lcd.begin(16, 2);
reset_LCD();

pinMode(BUZZER, OUTPUT);
}

char* readStr() {
uint8_t idx = 0;
char* str = (char*)malloc(128 * sizeof(char));

while (Serial.available() && idx < 128) {


str[idx] = Serial.read();
idx++;
delay(2);
}
for ( ; idx < 128 ; idx++) {
str[idx] = '\0';
}

return str;
}

void serialEvent() {
while (Serial.available()) {
char* string;
Serial.setTimeout(-1);
string = readStr();
Serial.print("Received: ");
Serial.println(string);

char substr[16];
for (uint8_t c = 0 ; c < 128 && string[c] != '\0' && string[c] != '\r' && string[c] != '\n' ; c
+= 16) {
for (uint8_t offset = 0 ; offset < 15 ; offset++) {
if (string[c + offset] != '\0' && string[c + offset] != '\r' && string[c + offset] != '\n') {
substr[offset] = string[c + offset];
} else {
substr[offset] = '\0';
}
}

reset_LCD();
print_string(substr);
}

free((void*)string);
}
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
}

void loop() {
}

72) Arduino Analog Style LED POV Clock


COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

LED (generic)

× 17
Hall Effect Sensor

× 1

Resistor 100 ohm

× 17

DC motor (generic)
× 1

Boost (Step Up) Switching Regulator, Fixed

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


The electronic part contains the Arduino Nano 17 LED diodes and the
Hall effect sensor. LED Diode groups d1-d11, d12-d16 and d17 are of
different color for better visual effect.The device is powered by a
lithium ion battery through a step-up converter.
The most difficult part of the projects for me was mechanical stability.
In the first attempt, the battery was set eccentrically and at a higher
speed of rotation there was a huge vibration. Then I made a
modification and put the battery in the center of rotation.

For rotation I use a 12V electric motor connected to a variable power


supply so the speed of rotation of the device can be easy controlled.
Depending on the speed of rotation of the device, in the code you need
to set the value of "delayMicroseconds" to a determined value.
The presented video is not clear enough, because for this purpose I
need a camera with a better frames per second.
SCHEMATICS

CODE

// hobbyprojects
// ArduinoNanoPropellerLEDAnalogClock20190403A

int LED1 = 2;
int LED2 = 3;
int LED3 = 4;
int LED4 = 5;
int LED5 = 6;
int LED6 = 7;
int LED7 = 8;
int LED8 = 9;
int LED9 = 10;
int LED10 = 11;
int LED11 = 12;
int LED12 = A1;
int LED13 = A2;
int LED14 = A3;
int LED15 = A4;
int LED16 = A5;

int sensorPin = A0;

unsigned int n,ADCvalue,propeller_posn;


unsigned long previousTime = 0;

byte hours = 12; // set hours


byte minutes = 15; // set minutes
byte seconds = 00; // set seconds

int val;

void setup()
{
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(LED4,OUTPUT);
pinMode(LED5,OUTPUT);
pinMode(LED6,OUTPUT);
pinMode(LED7,OUTPUT);
pinMode(LED8,OUTPUT);
pinMode(LED9,OUTPUT);
pinMode(LED10,OUTPUT);
pinMode(LED11,OUTPUT);
pinMode(LED12,OUTPUT);
pinMode(LED13,OUTPUT);
pinMode(LED14,OUTPUT);
pinMode(LED15,OUTPUT);
pinMode(LED16,OUTPUT);

pinMode(sensorPin,INPUT_PULLUP);

if(hours == 12)
hours = 0;
}

void loop()
{
val = digitalRead(sensorPin);

while (val == LOW)


{
val = digitalRead(sensorPin);
}

if (millis() >= (previousTime))


{
previousTime = previousTime + 1000;
seconds = seconds+1;
if (seconds == 60)
{
seconds = 0;
minutes = minutes+1;
}
if (minutes == 60)
{
minutes = 0;
hours = hours+1;
}
if (hours == 12)
{
hours = 0;
}
}

propeller_posn=30;
n=0;

while(n < 60)


{

drawMinuteMarker();
if ((propeller_posn==0) || (propeller_posn==5) || (propeller_posn==10) ||
(propeller_posn==15) || (propeller_posn==20) || (propeller_posn==25) ||
(propeller_posn==30) || (propeller_posn==35) || (propeller_posn==40) ||
(propeller_posn==45) || (propeller_posn==50) || (propeller_posn==55))
drawHourMarker();

if ((propeller_posn==0) || (propeller_posn==15) || (propeller_posn==30) ||


(propeller_posn==45))
drawQuarterMarker();

if((propeller_posn == hours*5) || (( propeller_posn == 0 ) && (hours == 0)))


drawHoursHand();

if(propeller_posn == minutes)
drawMinutesHand();

if(propeller_posn == seconds)
drawSecondsHand();

delayMicroseconds(140); // for LED pixel width (change the value according to motor
speed. Increase for low speed, decrease for high speed motor)

displayClear();

drawInner_Circle();

delayMicroseconds(600); // for the gap between LED pixels/minutes markers (change the
value according to motor speed. Increase for low speed, decrease for high speed motor)

n++;
propeller_posn++;
if(propeller_posn == 60)
propeller_posn=0;
}

val = digitalRead(sensorPin);

while (val == HIGH)


{
val = digitalRead(sensorPin);
}
}

//=========================
void displayClear()
{
digitalWrite(LED1,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED3,LOW);
digitalWrite(LED4,LOW);
digitalWrite(LED5,LOW);
digitalWrite(LED6,LOW);
digitalWrite(LED7,LOW);
digitalWrite(LED8,LOW);
digitalWrite(LED9,LOW);
digitalWrite(LED10,LOW);
digitalWrite(LED11,LOW);
digitalWrite(LED12,LOW);
digitalWrite(LED13,LOW);
digitalWrite(LED14,LOW);
digitalWrite(LED15,LOW);
digitalWrite(LED16,LOW);
}

void drawMinuteMarker()
{
digitalWrite(LED16,HIGH);
}

void drawHourMarker()
{
digitalWrite(LED15,HIGH);
digitalWrite(LED14,HIGH);
}

void drawQuarterMarker()
{
digitalWrite(LED13,HIGH);
digitalWrite(LED12,HIGH);
}

void drawHoursHand()
{
digitalWrite(LED1,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED4,HIGH);
digitalWrite(LED5,HIGH);
digitalWrite(LED6,HIGH);
digitalWrite(LED7,HIGH);
}

void drawMinutesHand()
{
digitalWrite(LED1,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED4,HIGH);
digitalWrite(LED5,HIGH);
digitalWrite(LED6,HIGH);
digitalWrite(LED7,HIGH);
digitalWrite(LED8,HIGH);
digitalWrite(LED9,HIGH);
}

void drawSecondsHand()
{
digitalWrite(LED1,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,HIGH);
digitalWrite(LED4,HIGH);
digitalWrite(LED5,HIGH);
digitalWrite(LED6,HIGH);
digitalWrite(LED7,HIGH);
digitalWrite(LED8,HIGH);
digitalWrite(LED9,HIGH);
digitalWrite(LED10,HIGH);
digitalWrite(LED11,HIGH);
}

void drawInner_Circle()
{
digitalWrite(LED1,HIGH);
delayMicroseconds(30);
digitalWrite(LED1,LOW);
}

73) Arduino Darkness Activated Ghots


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

9V Battery Clip

× 1
RobotGeek Light Sensor
We used a photo resistor, also
know as a LDR ( Light Dependent
× 1
Resistor ), i would recommend
this as its cheaper and serves the
purpose.
9V battery (generic)

× 1
NECESSARY TOOLS AND MACHINES
Laser cutter (generic)

Soldering iron (generic)

Hot glue gun (generic)


APPS AND ONLINE SERVICES
Arduino IDE

circuito.io

ABOUT THIS PROJECT


Ever wondered if we could scare our friends in the dark and have a
good laugh? Ever wondered if we could create a simple artificial ghost
and haunt your house?!
Well here is a system that we devised that does exactly so, the system
uses an Arduino and the code and schematics were created
with Circuito.io ( a fun and easy software that creates the founding
blocks of you projects, great for beginners, do check it out! ). Follow
on to see how our ''Ghost'' works and how we made it!
This idea came up with the often occurring fear of Darkness! Our
system works with the help of a light sensor, which detects the light
intensity in the room. Using this the program gets activated when the
lights are put off at night, in other words when it's completely dark. We
then cleverly recorded and manipulated are voices to make it sound
like a ghost. If the person who is pranked turns on the light scared the
voice immediately stops. Giving the effect as though there is a real
ghost in the room, giving it a haunted feeling and making you roll with
laughter as you see your friend freak out!!!
MECHANISM
We made the device portable and small so that it can fit in any small
hiding place in your house. We decided to hide it in a book, more of
that in the next steps. As we didn't have an Arduino audio shield, we
hacked our smartphone to fit into our device. We figure that we needed
to click on two buttons, the ''Play'' and the ''Skip''. To do this we used
servo motors having tips wrapped in foil, which clicks on the screen
either playing or skipping the audio clips. All of the components were
mounted on a custom laser cut part that we modeled.
LET'S GET MAKING!
Materials Needed:

An Arduino UNO, a Photoresistor & a Switch


Arduino UNO
LDR ( Photo resistor)
2 x 9g Micro Servo Motors
Switch
9 volt battery + clip
Jumper wire
2 x rubber bands
And your smartphone!
Assembling the system:
Start by getting the laser-cutting file cut,( though keep in mind that it
needs to fit your smartphone) you will need to make few adjustments.
Once done peel the protective layer.

The lasercut white acrylic

Opening exposing display


Mount the piece, simply with rubber bands
Squirt out dabs of hot glue around the servo, making sure that the horns
touch the required buttons. Stick both of them firmly in place, you can
then move and with the switch and stick the Arduino UNO with a strip
of double sided tape. (Follow the pictures to better understand the
arrangement).
over the button

glueing the servos


make sure the horns are parallel

mount the arduino with tape


MAKING THE ALUMINIUM TABS:
Take the leftover pieces of acrylic from the slot and break it into two
small tabs. Wrap them with foil and connect arduino's ground pin to it,
imitating them to act like your fingers and the touch screen

aluminium tabs attached to the horns

hot glued
smooth surface sticking out

the tabs shouldn't touch


make sure the aluminium tabs are slightly at an angle
Wire them all up, hooking up the servo motors to the Arduino with
jumper wires. Follow the schematics.

Circuito helped us get an acurate schematics


Soldering...
It's complete
THE AUDIO RECORDINGS:
This is one of the most fun parts, it's when your ghost comes to life.
Record some spooky ghost lines and be creative in making it scary with
sound effects! Then upload the clips to your smartphone in the right
sequence and you are nearly done!
recording our spooky voices and adding sound effect
YOU'RE DONE!
We had made this cut out book a while back and found it a perfect
object to conceal the system. Try and find a none obvious hiding spot
or an object like a pot or an old regulator case, etc...
You are ready, wait till evening and prank your friend by slipping in
your smartphone and clicking a switch! This spooked us out to even
though we made it. It got us hilarious results and we feel it definitely
does give a shiver!
our Fake book!

as you can see this FAKE BOOK is the perfect size

Time to put it on
Simply put in the whole device
make sure the LDR sticks out

Now place it on a table..


.
..or a Shelf

SCHEMATICS
CODE

#include <Servo.h>
Servo servo1;
Servo servo2;
int pos1 = 0;
int pos2 = 0;

int ldr = A0;


int sensor_value = 0;
int thresh = 150;
bool state = false;

void play(){
for (pos1 = 0; pos1 <= 180; pos1 += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos1 = 180; pos1 >= 0; pos1 -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
while(true);
}

void next_clip(){
for (pos2 = 0; pos2 <= 180; pos2 += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos2 = 180; pos2 >= 0; pos2 -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
while(true);
}

void setup() {
// put your setup code here, to run once:
servo1.attach(7);
servo2.attach(8);
Serial.begin(9600); //for debugging only

void loop() {
// put your main code here, to run repeatedly:
sensor_value = analogRead(ldr);

//the moment lights go off the first clip starts to play


if (sensor_value < thresh){
play();
state = true;

}
//once the victim is scared and tries to turn on the lights. play next clip
else if(sensor_value > thresh && state == true){
next_clip();
play();
state = false;
}

//do nothing
}

74) Arduino and Vibration Sensor with Relay


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

SW-420 Vibration sensor module


× 1

Optocoupler PC817
× 1
Transistor BC 547
× 1

1N4007 – High Voltage, High


Current Rated Diode
× 1

Relay 5V DC
× 1

5 mm LED: Red
A second LED is used to show the
× 1
relay contact ON OFF

Resistor 220 ohm

× 2

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

4xAA battery holder


In this project I used a battery
× 1
holder with 3 AA batteries
ABOUT THIS PROJECT
The idea: A big light must flash 3 times when at long distance shooting the
target is hit. (Target is a metal round piece attached on a metal frame)
How it works: When the target is hit, the sensitive vibration sensor, fixed
on the back of the target frame, will detect vibration. To indicate the target
was hit, the light will flash 3 times. (2sec ON, 1 sec OFF, 3 times)
The sensor module is powered by the Arduino. With the help of the
Optocoupler PC817 we keep the circuit for the relay seperated from the
Arduino UNO.
The relay is powered by the external source, in this case 3x AA battery.
SCHEMATICS
CODE

//Vibration Sensor Module (Code)Arduino with relay and external 5V power source.

int vib_pin=2;
int led_pin=13;

// put your setup code here, to run once:


void setup() {
pinMode(vib_pin,INPUT);
pinMode(led_pin,OUTPUT);
}

// put your main code here, to run repeatedly:


void loop() {
int val;
val=digitalRead(vib_pin);
if(val==1)
{
digitalWrite(led_pin,LOW);
delay(2000);
digitalWrite(led_pin,HIGH);
delay(1000);
digitalWrite(led_pin,LOW);
delay(2000);
digitalWrite(led_pin,HIGH);
delay(1000);
digitalWrite(led_pin,LOW);
delay(2000);
digitalWrite(led_pin,HIGH);
delay(1000);

}
else
digitalWrite(led_pin,HIGH);
}

75) Arduino Tic Tac Toe Board Game with Robotic Arm
COMPONENTS AND SUPPLIES
4 x 4 Matrix Array 16 Key Membrane Switch
Keypad Keyboard for Arduino × 1

Connector - DB9 Male Socket


× 1

Female Header 4 position 0.1" spacing


This mates with the X-Arm Serial port × 1
header
Connector DB9 - Female Plug
× 1

Enclosure Plastic 5.5" (L) x 3.25" (W) x 1/5"


(H)
Any plastic enclosure to house the
Mega2560 and room to mount the DB-9 × 1
Socket. Punch or drill out holes for socket
and connectors of Mega2560, and mount the
Keypad on top panel of enclosure.
Robotic Arm with 6DOF - Lewansoul model
X-Arm × 1

BSIRI TicTacToe Classic Board Games


Noughts and Crosses × 1

Nylon spacers (for board mounting)


× 4

Nylon screws 4-40 size (for mounting board)


× 1

Nylon nuts (for mounting board)


× 4

Arduino Mega 2560 & Genuino Mega 2560


Substituted Elegoo LYSB01H4ZDYCE-
ELECTRNCSMEGA 2560 R3 Board × 1
NECESSARY TOOLS AND MACHINES

ABOUT THIS PROJECT


I wanted to use the Lewansoul's robotic arm (X-arm) ( to play a real
board version of tic-tac-toe to illustrate the movement of the arm to
pickup and place pieces into positions in a game environment. The
robotic arm is controlled by the Arduino Mega 2560 and input from the
player ("X") is confirmed by a membrane keypad using keys 1-9 to
represent each of the board positions 1-9. I used an existing tic-tac-toe
sketch (see contributor) from GitHub, that uses the MinMax algorithm
to determine which move the computer should make after the player
makes each move. I added to this program the code to control the X-
arm position using the stored action groups in the X-arm controller for
each possible position 1-9 of the board. So for a specific move by the
computer to play the next position, say, position 4, the x-arm would be
sent an action group command "4" to pick up the computer piece (in
this case, the computer is "O") and place it in the number 4 position on
the tic-tac-toe game board.

SCHEMATICS

Tic-tac-toe schematic
Tic-Tac-toe Breadboard
CODE

//
//BobN2Tech 03-22-18 add Xarm code for robotic control and Keypad input code
//Thanks to https://github.com/klauscam/ArduinoTicTacToe for the tic-tac-toe algorithm
//this code requires mega2560 which uses serial port 3 (serial3) to control the Lewansoul
xarm
//note: actiongroups 0-8 must be downloaded to the xarm controller prior
//to using this program. Action group numbers 0 to 8 represent the board positions that
//will be placed the moved piece. Initially has to be done manually (train the x-arm) to
determine each board position
//where the xarm will place the computer move piece.
//action group 100 is preloaed for the initial position of the arm (recommend standing up)
//action group 9 is for moving the arm as computer winning game - does some fancy
gyration
//optional action group 10 is for a draw - does some gyration
//optional action group 11 is for a losing - does some humble gesture.
//action group 12 is places arm into position where it will get the "O" pieces
//The computer will never lose!
//
int difficulty=8;
//xarm
#include <LobotServoController.h>
//Not using software serial
//#define rxPin 2 //software serial
//#define txPin 3 //software serial

//SoftwareSerial mySerial(rxPin, txPin);


//LobotServoController myse(mySerial);

//hardware serial - use only if not using serial0 ow it conflicts


LobotServoController myse(Serial3);

const int speed = 100; //percent of action speed set in group. 100 = 100% = same speed as
programmed, 50 = 1/2 speed, 200 = twice speed
int lastComputerMove = -1;
bool xarmConnected = false;

//keypad
#include <Keypad.h>

const byte ROWS = 4; //four rows


const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
char customKey;
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS,
COLS);
//

void setup(){
Serial.begin(9600);
while(!Serial);
digitalWrite(13,HIGH);
Serial3.begin(9600);
while(!Serial3);
//xarm code
//
int moveNo = 0;
pinMode(13,OUTPUT);
// mySerial.begin(9600);
// while(!mySerial);
// digitalWrite(13,HIGH);

//check if xarm is connected - send the initial positon


myse.runActionGroup(100,1);

if(myse.waitForStopping(5000)) //Waiting for the action group is completed, or be stopped


or timeout. The unit of the parameter(timeout) is milliscond. finish or stop, you will get a
true. timeout, you will get a false
{
Serial.println("Xarm is connected");
digitalWrite(13, LOW);
xarmConnected = true;
}
else
Serial.println("X-Arm not connected");

//test - change to loop for 9 positions

if (xarmConnected)
{

for (int i = 0;i <9; i++)


{
myse.setActionGroupSpeed(i,speed); //Set the running speed of i action group at % speed
of programmed
delay (1000);
//optional test all action groups are working
// Serial.println("xarm move to position " + String(i));
// myse.runActionGroup(i,1);
// delay(3000);

}
//optional
// myse.setActionGroupSpeed(100,speed); //Set the running speed of No.100 action group
at 1 sec
// delay(1000);

//put arm back into stand up as initial position (assume group 100)

// myse.runActionGroup(100,1);

// delay(2000);
xarmMove (12); //put arm into position for getting the pieces

delay (5000);
//
}
}

char displayChar(int c) {
switch(c) {
case -1:
return 'X';
case 0:
return ' ';
case 1:
return 'O';
}
}

void draw(int board[9]) {


Serial.print(" ");Serial.print(displayChar(board[0])); Serial.print(" |
");Serial.print(displayChar(board[1])); Serial.print(" |
");Serial.print(displayChar(board[2])); Serial.println(" ");
Serial.println("---+---+---");
Serial.print(" ");Serial.print(displayChar(board[3])); Serial.print(" |
");Serial.print(displayChar(board[4])); Serial.print(" |
");Serial.print(displayChar(board[5])); Serial.println(" ");
Serial.println("---+---+---");
Serial.print(" ");Serial.print(displayChar(board[6])); Serial.print(" |
");Serial.print(displayChar(board[7])); Serial.print(" |
");Serial.print(displayChar(board[8])); Serial.println(" ");
}

int win(const int board[9]) {


//list of possible winning positions
unsigned wins[8][3] = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
int winPos;
for(winPos = 0; winPos < 8; ++winPos) {
if(board[wins[winPos][0]] != 0 && board[wins[winPos][0]] == board[wins[winPos][1]]
&& board[wins[winPos][0]] == board[wins[winPos][2]])
return board[wins[winPos][2]];
}
return 0;
}
int minimax(int board[9], int player, int depth) {
//check the positions for players
int winner = win(board);
if(winner != 0) return winner*player;

int move = -1;


int score = -2;
int i;
for(i = 0; i < 9; ++i) {

if(board[i] == 0) {
board[i] = player;
int thisScore=0;
if (depth<difficulty){
thisScore = -minimax(board, player*-1,depth+1);
}

if(thisScore > score) {


score = thisScore;
move = i;

}
//choose the worst move for opponent
board[i] = 0;
}
}
if(move == -1) return 0;
return score;

void computerMove(int board[9])


{
int move = -1;
int score = -2;
int i;
for(i = 0; i < 9; ++i) {
if(board[i] == 0) {
board[i] = 1;
int tempScore = -minimax(board, -1, 0);
board[i] = 0;
if(tempScore > score) {
score = tempScore;
move = i;
lastComputerMove = i;
}
}
}
//returns a score based on minimax tree at a given node.
board[move] = 1;
}

void playerMove(int board[9])


{
int move = 0;
int bmove =0;
String smove;

do {

// Get value from custom keypad but start with keypad 1 = board 0;
Serial.println("\nInput move ([1..9]): ");
while ((customKey = customKeypad.getKey())== NO_KEY)
{delay(100);}

Serial.println(customKey);
//convert to string so can convert char to integer -
smove = (String)customKey;
bmove = smove.toInt()-1; //use keypad so will start with numbers 1-9 to correspond to
physical board layout
move = bmove;
//

Serial.println("\n");
} while ((move >= 9 || move < 0) || board[move] != 0);
board[move] = -1;
}

void xarmMove (int action)


{
if (!xarmConnected)
return;

myse.runActionGroup(action,1); //run action group once for each move

//test to get status while its running and do other things


Serial.println("Start RUNNING at " + String(millis())); //show total time

while (myse.isRunning()) //RAC


{

// Serial.println("IS STILL RUNNING" + String(millis())); //show total time


myse.receiveHandle(); //must include this, otherwise will never leave this loop

Serial.println("Action Completed at " + String(millis()));

Serial.println("FINISH XARM MOVE");

void loop(){
int board[9] = {0,0,0,0,0,0,0,0,0};
//x-arm Play only 1, playing 2 does not work correctly
// Serial.println("Would you like to play X(1) or O(2)?");
Serial.println("Press 1 to start playing - you are 'X' and Computer is 'O'");
/* get input from computer keyboard
while(Serial.available()==0)
{
delay(100);
}

int player=Serial.parseInt();
Serial.println(player);
*/

// Get value from custom keypad ;


int player;
String s;
while ((customKey = customKeypad.getKey())== NO_KEY)
{delay(100);}

Serial.println(customKey);
//convert to string so can convert char to integer
s = (String)customKey;
player = s.toInt();
//
unsigned turn;
for(turn = 0; turn < 9 && win(board) == 0; ++turn) {
if((turn+player) % 2 == 0)
{
computerMove(board);

Serial.println("xarm move is " + String(lastComputerMove));

if (lastComputerMove != -1 & lastComputerMove < 9)


xarmMove (lastComputerMove); //action groups index start at 0
}
else
{
draw(board);
playerMove(board);
}
}
switch(win(board)) {
case 0:
Serial.println("It's a draw.\n");
//send the initial positon
xarmMove (12);
break;
case 1:
draw(board);
Serial.println("You lose.\n");
xarmMove (9);
break;
case -1:
Serial.println("You win!\n");
xarmMove (11);
break;
}
}
76) Arduino Spectrum Analyzer with RGN LEDs
COMPONENTS AND SUPPLIES
Arduino Nano R3

× 1

Resistor 22.1k ohm


I just used 22k Ohm
× 1
Resistor 221k ohm
× 2
I just used 220k Ohm

MSGEQ7
× 1

Capacitor 33pF
× 1

Capacitor 100 nF

× 2

Capacitor 10 nF

× 1

Adressable RGB-LED Strip


× 1

USB Connector, USB Type B

× 1

Female Header 8 Position 1 Row


(0.1")
× 1

Wire, Wrapping Wire

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Solder Wire, Lead Free

Hot glue gun (generic)

Bantam Tools Desktop PCB Milling


Machine

ABOUT THIS PROJECT


The project is to visualize an audio signal with a RGB Led Stripe. The
used MSGE7 have 7 bandpasses, thats why I made 7 lines with the
LED stripes.
The circuit board is designed with Eagle and made by a circuit board
milling mashine.
For the Power supply I used a normal USB Type B socket. On the
Bottom are the connectors for the AUX wire and X4 is for the LED-
Stripe.
The USB-Interface is used for the power supply.
MSGEQ7, Arduino Nano and the jumper are fixed on one circut board.
I just soldered the single stripes behid each other and glued them on
transperend PE.
This is how its looks inside the case.
The circuit board is in a 3D printed case with Aux sockets for input and
output signal.
SCHEMATICS
CODE

//Arduino Spectrum Analyzer with RGB-LED Stripe and MSGEQ7


// declarations for the Neopixel by Adafruit
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 4 // Pin for the RGB Stripe
#define NUMPIXELS 70 // Number of Pixels
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB +
NEO_KHZ800);
int strobePin = 2; // Strobe Pin on the MSGEQ7
int resetPin = 3; // Reset Pin on the MSGEQ7
int outPin = A0; // Output Pin on the MSGEQ7
int level[7]; // An array to hold the values from the 7 frequency bands
int l;
uint32_t aus = pixels.Color(0,0,0);
uint32_t gr = pixels.Color(0,200,0);
uint32_t grb = pixels.Color(0,160,40);
uint32_t grbl = pixels.Color(0,120,80);
uint32_t gbl = pixels.Color(0,80,120);
uint32_t bl = pixels.Color(0,40,160);
uint32_t blr = pixels.Color(0,0,200);
uint32_t blro = pixels.Color(40,0,160);
uint32_t bro = pixels.Color(80,0,120);
uint32_t ro = pixels.Color(120,0,80);
uint32_t rog = pixels.Color(160,0,0);

void setup()
{
Serial.begin(9600);
pinMode(strobePin, OUTPUT); // Define our pin modes
pinMode(resetPin, OUTPUT);
pinMode(outPin, INPUT);
pinMode(3,OUTPUT);
digitalWrite(resetPin, LOW); // Create an initial state for our pins
digitalWrite(strobePin, LOW);
delay(1);
digitalWrite(resetPin, HIGH); // Reset the MSGEQ7 as per the datasheet timing diagram
delay(1);
digitalWrite(resetPin, LOW);
digitalWrite(strobePin, HIGH);
delay(1);
pixels.begin(); // enables Adafruit Neopixels
pixels.show(); // reset Pixels
for (int i = 0; i < 70; i++)
{
int ii = i-5; //snake effect at the start
pixels.setPixelColor(i, gr);
pixels.setPixelColor(ii, aus);
pixels.show();
delay(20);
}
}
void LEDaus1(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
for (int i=a; i <=k; i++)
{
pixels.setPixelColor(i, aus);
pixels.show();
}
}
void LEDaus2(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
for (int i=a; i >=k; i--)
{
pixels.setPixelColor(i, aus);
pixels.show();
}
}
void LED0(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k, uint32_t gr)
{
pixels.setPixelColor(a, gr);
for (int i=b; i <= k; i++) pixels.setPixelColor(i, aus);
}
void LED1(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
for (int i=k; i <= c; i++) pixels.setPixelColor(i, aus);
}
void LED2(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
for (int i=d; i <= k; i++) pixels.setPixelColor(i, aus);
}
void LED3(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
pixels.setPixelColor(d, gbl);
for (int i=k; i <= e; i++) pixels.setPixelColor(i, aus);
}
void LED4(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
pixels.setPixelColor(d, gbl);
pixels.setPixelColor(e, bl);
for (int i=f; i <= k; i++) pixels.setPixelColor(i, aus);
}
void LED5(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
pixels.setPixelColor(d, gbl);
pixels.setPixelColor(e, bl);
pixels.setPixelColor(f, blr);
for (int i=k; i <= g; i++) pixels.setPixelColor(i, aus);
}
void LED6(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
pixels.setPixelColor(d, gbl);
pixels.setPixelColor(e, bl);
pixels.setPixelColor(f, blr);
pixels.setPixelColor(g, blro);
for (int i=h; i <= k; i++) pixels.setPixelColor(i, aus);
}
void LED7(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
pixels.setPixelColor(d, gbl);
pixels.setPixelColor(e, bl);
pixels.setPixelColor(f, blr);
pixels.setPixelColor(g, blro);
pixels.setPixelColor(h, bro);
for (int i=k; i <= j; i++) pixels.setPixelColor(i, aus);
}
void LED8(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
pixels.setPixelColor(d, gbl);
pixels.setPixelColor(e, bl);
pixels.setPixelColor(f, blr);
pixels.setPixelColor(g, blro);
pixels.setPixelColor(h, bro);
pixels.setPixelColor(j, ro);
pixels.setPixelColor(k, aus);
}
void LED9(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
pixels.setPixelColor(a, gr);
pixels.setPixelColor(b, grb);
pixels.setPixelColor(c, grbl);
pixels.setPixelColor(d, gbl);
pixels.setPixelColor(e, bl);
pixels.setPixelColor(f, blr);
pixels.setPixelColor(g, blro);
pixels.setPixelColor(h, bro);
pixels.setPixelColor(j, ro);
pixels.setPixelColor(k, rog);
}
void abfolge(int a,int b,int c,int d,int e,int f,int g,int h,int j,int k)
{
switch (l)
{
case 93 ... 104:/*<---------------------------------------first LED area-------------------------------
-------------------------*/
LED0(a,b,c,d,e,f,g,h,j,k,gr);
break;
case 105 ... 139:/*<---------------------------------------second LED area--------------------------
----------------------------*/
LED1(a,b,c,d,e,f,g,h,j,k);
break;
case 140 ... 164:/*<---------------------------------------third LED area-----------------------------
--------------------------*/
LED2(a,b,c,d,e,f,g,h,j,k);
break;
case 165 ... 199:/*<---------------------------------------fourth LED area---------------------------
---------------------------*/
LED3(a,b,c,d,e,f,g,h,j,k);
break;
case 200 ... 234:/*<---------------------------------------fith LED area------------------------------
--------------------------*/
LED4(a,b,c,d,e,f,g,h,j,k);
break;
case 235 ... 269:/*<---------------------------------------sixth LED area-----------------------------
--------------------------*/
LED5(a,b,c,d,e,f,g,h,j,k);
break;
case 270 ... 304:/*<---------------------------------------seventh LED area--------------------------
---------------------------*/
LED6(a,b,c,d,e,f,g,h,j,k);
break;
case 305 ... 339:/*<---------------------------------------eighth LED area---------------------------
---------------------------*/
LED7(a,b,c,d,e,f,g,h,j,k);
break;
case 340 ... 374:/*<---------------------------------------nineth LED area---------------------------
---------------------------*/
LED8(a,b,c,d,e,f,g,h,j,k);
break;
case 375 ... 1000:/*<---------------------------------------tenth LED area---------------------------
---------------------------*/
LED9(a,b,c,d,e,f,g,h,j,k);
break;
}
}
void loop()
{
// Cycle through each frequency band by pulsing the strobe.
for (int i = 0; i < 7; i++)
{
digitalWrite (strobePin, LOW);
delayMicroseconds (100); // Delay necessary due to timing diagram
level[i] = analogRead (outPin);
digitalWrite (strobePin, HIGH);
delayMicroseconds (100); // Delay necessary due to timing diagram
}
/*-----------------------------------------------------------Band1(For the first LED stripe)----------
-----------------------------------------------------*/
// allocation for the Numbers of LEDs
l = level [0];
abfolge(0,1,2,3,4,5,6,7,8,9);
if (l < 92) LEDaus1(0,1,2,3,4,5,6,7,8,9);
/*-----------------------------------------------------------Band2(For the second LED stripe)-------
--------------------------------------------------------*/
// allocation for the Numbers of LEDs
l = level [1];
abfolge(19,18,17,16,15,14,13,12,11,10);
if (l < 92) LEDaus2(19,18,17,16,15,14,13,12,11,10);
/*-----------------------------------------------------------Band3(For the third LED stripe)---------
------------------------------------------------------*/
// allocation for the Numbers of LEDs
l = level [2];
abfolge(20,21,22,23,24,25,26,27,28,29);
if (l < 92) LEDaus1(20,21,22,23,24,25,26,27,28,29);
/*-----------------------------------------------------------Band4(For the fourth LED stripe)--------
-------------------------------------------------------*/
// allocation for the Numbers of LEDs
l = level [3];
abfolge(39,38,37,36,35,34,33,32,31,30);
if (l < 92) LEDaus2(39,38,37,36,35,34,33,32,31,30);
/*-----------------------------------------------------------Band5(For the fifth LED stripe)----------
-----------------------------------------------------*/
// allocation for the Numbers of LEDs
l = level [4];
abfolge(40,41,42,43,44,45,46,47,48,49);
if (l < 92) LEDaus1(40,41,42,43,44,45,46,47,48,49);
/*-----------------------------------------------------------Band6(For the sixth LED stripe)---------
------------------------------------------------------*/
// allocation for the Numbers of LEDs
l = level [5];
abfolge(59,58,57,56,55,54,53,52,51,50);
if (l < 92) LEDaus2(59,58,57,56,55,54,53,52,51,50);
/*-----------------------------------------------------------Band7(For the seventh LED stripe)------
---------------------------------------------------------*/
// allocation for the Numbers of LEDs
l = level [6];
abfolge(60,61,62,63,64,65,66,67,68,69);
if (l < 92) LEDaus1(60,61,62,63,64,65,66,67,68,69);
}
17) Arduino Line Follower Robot
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

BO motor
× 1

wheels
× 1
ir sensor
× 1

Texas Instruments Dual H-Bridge


motor drivers L293D
× 1

Custom PCB

× 1

9V battery (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Components used:
Piece of cardboard/ Acrylic sheet
Arduino Uno
IR sensor
BO motor
Wheels
Caster wheel
L293d IC
PCB
Flexible wire
Battery
Fix all components on acrylic sheet and make a chassis as shown in
pictures.
you can make this circuit on dotted pcb like this.

or can use this type of professional looking PCB.


SCHEMATICS
CODE

//
//for Line Following Robot using 2IR sensors
int lm1=8; //left motor output 1
int lm2=9; //left motor output 2
int rm1=10; //right motor output 1
int rm2=11; //right motor output 2
int sl=13; //sensor 1 input (left)
int sr=12; //sensor 2 input (right)
int SlV=0;
int SrV=0;
int led=A0;
void setup()
{
pinMode(lm1,OUTPUT);
pinMode(lm2,OUTPUT);
pinMode(rm1,OUTPUT);
pinMode(rm2,OUTPUT);
pinMode(led,OUTPUT);
pinMode(sl,INPUT);
pinMode(sr,INPUT);
sTOP();
}
void loop()
{
SlV=digitalRead(sl);
SrV=digitalRead(sr);
if(SrV==LOW && SlV== LOW)
{
ForWard();
}
if(SrV==HIGH && SlV== LOW)
{
Left();
}
if(SrV==LOW && SlV== HIGH)
{
Right();
}
if(SrV==HIGH && SlV== HIGH)
{
sTOP();
}
}
void ForWard()
{
digitalWrite(lm1,HIGH);
digitalWrite(lm2,LOW);
digitalWrite(rm1,HIGH);
digitalWrite(rm2,LOW);
}
void BackWard()
{
digitalWrite(lm1,LOW);
digitalWrite(lm2,HIGH);
digitalWrite(rm1,LOW);
digitalWrite(rm2,HIGH);
}
void Left()
{
digitalWrite(lm1,LOW);
digitalWrite(lm2,HIGH);
digitalWrite(rm1,HIGH);
digitalWrite(rm2,LOW);
}
void Right()
{
digitalWrite(lm1,HIGH);
digitalWrite(lm2,LOW);
digitalWrite(rm1,LOW);
digitalWrite(rm2,HIGH);
}
void sTOP()
{
digitalWrite(lm1,LOW);
digitalWrite(lm2,LOW);
digitalWrite(rm1,LOW);
digitalWrite(rm2,LOW);
}

78) Arduino Automated Plant Watering System


COMPONENTS AND SUPPLIES
Arduino Nano R3

× 1

DHT11 Temperature & Humidity


Sensor (4 pins)
× 1
Seeed Grove - OLED Display 1.12''
V2 × 1

Espressif ESP8266 ESP-01

× 1

Relay (generic)
× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Hot glue gun (generic)

ABOUT THIS PROJECT

My country has been badly affected by climate change due to heavy


deforestation. So many campaigns arose planting more trees. However,
to reduce my effort in gardening, I made something that water my
plants based on an Android app.
The concept is simple: I designed a web server using ESP8266.
Changed index a bit. Also, the ESP8266 controls the relay to water
pump.
Pump to watering
The second component is an Arduino Nano, which takes readings from
DHT11 and displays on an OLED.
Complete control box

SCHEMATICS
CODE
Automated Garden Watering Nano

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

#define DHTPIN 2 // what pin we're connected to


#define DHTTYPE DHT11 // DHT 11
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

// Initialize DHT sensor for normal 16mhz Arduino


DHT dht(DHTPIN, DHTTYPE);
String info;
boolean watering= false, status=false;
void setup()
{
Wire.begin();
dht.begin(); // initialize dht
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// initialize with the I2C addr 0x3C (for
the 128x32)(initializing the display)
Serial.begin(9600);
}
void displayTempHumid(){
delay(2000);
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius
float t = dht.readTemperature();
// Read temperature as Fahrenheit
float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
display.clearDisplay(); // clearing the display
display.setTextColor(WHITE); //setting the color
display.setTextSize(1); //set the font size
display.setCursor(5,0); //set the cursor coordinates
display.print("Failed to read from DHT sensor!");
return;
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print("Humidity: ");
display.print(h);
display.print(" %\t");
display.setCursor(0,10);
display.print("Temperature: ");
display.print(t);
display.print(" C");
display.setCursor(0,20);
display.print("Temperature: ");
display.print(f);
display.print(" F");
}

void loop()
{
displayTempHumid();
display.display();
}

Automated Garden Watering Esp8266

/*
* This sketch demonstrates how to set up a simple HTTP-like server.
* The server will set a GPIO pin depending on the request
* http://server_ip/gpio/0 will set the GPIO2 low,
* http://server_ip/gpio/1 will set the GPIO2 high
* server_ip is the IP address of the ESP8266 module, will be
* printed to Serial when the module is connected.
*/

#include <ESP8266WiFi.h>

const char* ssid = "ASH";


const char* password = "12345678";

// Create an instance of the server


// specify the port to listen on as an argument
WiFiServer server(80);

boolean waternow=false;

void setup() {
Serial.begin(9600);
delay(10);
pinMode(2, OUTPUT);

// Connect to WiFi network


Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {


delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");

// Start the server


server.begin();
Serial.println("Server started");

// Print the IP address


Serial.write(WiFi.localIP());
}

void loop() {
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}

// Wait until the client sends some data


Serial.println("new client");
while(!client.available()){
delay(1);
}

// Read the first line of the request


String req = client.readStringUntil('\r');
client.flush();

int val;

if (req.indexOf("manu/ON") != -1){
waternow=true;}
else if (req.indexOf("manu/OFF") != -1){
waternow=false;}

else {
Serial.println("invalid request");
client.stop();
return;
}

client.flush();

delay(1);
Serial.println("Client disonnected");
if (waternow==true){ digitalWrite(2, HIGH);
delay (30000);
waternow=false;}
else{digitalWrite(2, LOW);}

// The client will actually be disconnected


// when the function returns and 'client' object is detroyed
}

79) Full Control of Your Tv Using Alexa and Arduino IoT Cloud
COMPONENTS AND SUPPLIES

Arduino Nano 33 IoT

× 1

Resistor 330 ohm

× 1
IR receiver (generic)
× 1
ex. VS1838B
IR transmitter (generic)
× 1

Jumper wires (generic)

× 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino Web Editor

Arduino IoT Cloud

Arduino Amazon Alexa Official Arduino


Skill

ABOUT THIS PROJECT

Intro: Arduino IoT Cloud


Arduino IoT Cloud is a platform that enables anyone to build IoT
connected object with ease. In order to control our TV using Alexa,
we'll also be using the Official Arduino Alexa Skill.
If you are new to Arduino IoT Cloud, we advise to first take a look
at this introductory project, which will give you an overview and guide
you through the process of setting up one of the supported boards, IoT
Cloud Things and Properties and get you onboard.
Part 1: How to Control a TV Set
The easiest way to control any kind of television, is to act as if we were
its very own remote infrared controller. In order to do so, we'll have
to listen for the signals the remote will send, capture the data and
mimick it with our Arduino board. Once the circuit is assembled, we'll
upload this sketch to our board. It will traslate the IR signal bursts
generated by remote button presses into an array of unsigned integers.
Let's point the remote at the Arduino IR Receiver we built and press the
following buttons:
POWER/STANDBY
CHANNELS FROM 1 TO 9
VOLUME UP
VOLUME DOWN
MUTE
CHANNEL UP
CHANNEL DOWN
We'll see the values coming through the Serial Monitor, reported
as rawData. Let's take note of them into a text file for now, and assign
each list its own array name (chan1, chan2 and so on). The following
values are just for reference, and are generated by a Samsung's TV
remote.
CHANNEL 1
unsigned int chan1[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};
CHANNEL 2
unsigned int chan2[67] = {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};
CHANNEL 3
unsigned int chan3[67] = {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};
CHANNEL 4
unsigned int chan4[67] = {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};
CHANNEL 5
unsigned int chan5[67] = {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};
CHANNEL 6
unsigned int chan6[67] = {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};
CHANNEL 7
unsigned int chan7[67] = {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};
CHANNEL 8
unsigned int chan8[67] = {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};
CHANNEL 9
unsigned int chan9[67] = {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};
VOLUME UP
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};
VOLUME DOWN
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};
CHANNEL UP
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};
CHANNEL DOWN
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};
Part 2: Arduino IoT Cloud
From the main Arduino IoT Cloud page, we'll create a new Thing and
assign it a meaningful name. Let's call it TVRemoteController. We'll
then select the board we are going to use. For this tutorial we used an
Arduino Nano 33 IoT, but if you have another compatible board it will
also be fine, just keep in mind that the pinout and the behavior of the
IR library might change. If at this point you cannot see your board, you
might have skipped the Getting Started procedure we mentioned above,
if this is the case, go back through that process.
Once done, we'll add one Property to our Thing, it will represent our
TV set. Under the Smart Home category, select "TV" as Property Type,
set it as "Read & Write", and under "Update" select "When the value
changes".
Here it is what the Properties view of our Thing should look like at this
point:

Our newly created Thing's property view


Part 3: Arduino Web Editor
The time has come to click on the "EDIT SKETCH" button, which will
take us the Web Editor, where we can add some custom code to the
Sketch automatically generated by IoT Cloud.
The first thing we have to include is the IR Remote library, by Ken
Shirriff.
#include <IRremote.h>
We then have to setup one two-dimensional array for our channels, and
6 arrays for the commands we need. If you remember, in Part 1 we
captured some IR data which we'll now use to fill our arrays
const unsigned int chan[9][67] = {
{chan1},
{chan2},
{chan3},
{chan4},
{chan5},
{chan6},
{chan7},
{chan8},
{chan9}
};
const unsigned int volUp[67] = {...};
const unsigned int volDown[67] = {...};
const unsigned int chanUp[67] = {...};
const unsigned int chanDown[67] = {...};
const unsigned int onoff[67] = {...};
const unsigned int mute[67] = {...};
Let's then setup the IR library and the required frequency (for this kind of
application it will always be 38KHz)
IRsend irsend;
const int freq = 38;
We'll also need a function to send out IR commands and blink the built-in
LED (at this stage mostly for debugging purposes). The delay value used
will depend on the make and model of your television, so feel free to
tweak it if things aren't working as expected (wrong commands or no
commands received).
void sendIR(const unsigned int buf[]) {
digitalWrite(LED_BUILTIN, HIGH);
irsend.sendRaw(buf, 67, freq);
delay(300);
digitalWrite(LED_BUILTIN, LOW);
}
The final step is to complete the generated callback onTvChange() with
some custom code in order to send IR commands when the TV property is
changed by Alexa commands. For example, if the volume is increased, we
have to virtually press the button Volume Up, if the channel is set to 7, we
have to send the sequence for the channel 7 button, and so on.
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(volUp);
Serial.println("Volume requested:"+String(tv.getVolume())+"
Set:"+String(k));
}
prevVolume = tv.getVolume();
}
else 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()));
}
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 <IRremote.h>

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(volUp);
Serial.println("Volume requested:"+String(tv.getVolume())+"
Set:"+String(k));
}
prevVolume = tv.getVolume();
}
else 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

Breadboard (generic)

× 1
Buzzer
× 1

Photo resistor

× 1

LED (generic)

× 1

Single Turn Potentiometer- 10k


ohms
× 1

SparkFun Pushbutton switch 12mm

× 1

Resistor 10k ohm

× 2

Resistor 560 ohm


× 2

Jumper wires (generic)

× 12
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 a3f 208 // 208 Hz


#define b3f 233 // 233 Hz
#define b3 247 // 247 Hz
#define c4 261 // 261 Hz MIDDLE C
#define c4s 277 // 277 Hz
#define e4f 311 // 311 Hz
#define f4 349 // 349 Hz
#define a4f 415 // 415 Hz
#define b4f 466 // 466 Hz
#define b4 493 // 493 Hz
#define c5 523 // 523 Hz
#define c5s 554 // 554 Hz
#define e5f 622 // 622 Hz
#define f5 698 // 698 Hz
#define f5s 740 // 740 Hz
#define a5f 831 // 831 Hz

#define rest -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

LED (generic)

× 2

Resistor 221 ohm

× 2

Ultrasonic Sensor - HC-SR04


(Generic)
× 1

Buzzer

× 1

RC522 Card Reader


× 1

Real Time Clock


× 1
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()<120)
For every explanation or suggestion, feel free to comment below.
I'm sorry, I can't make my real schematics because with Fritzing I can't
compact the circuit, please forgive me ;-)

SCHEMATICS
CODE

#include <RFID.h>
#include <SPI.h>
#include <SR04.h>
#include <DS3231.h>
#include <Wire.h>
String ora;
String mins;
String orario;
DS3231 Clock;

#define ECHO_PIN 3
#define TRIG_PIN 4
#define green 5
#define red 6
#define buzz 8
#define RESET_DIO 9
#define SDA_DIO 10

#define delayRead 600

SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);


RFID RC522(SDA_DIO, RESET_DIO);

bool h12;
bool PM;
int attivo=false;
int statoattivato=0;
String codiceLetto;
String codiceAutorizzato = "5545A93980";

void setup(){
Wire.begin();
SPI.begin();
RC522.init();
pinMode(buzz,OUTPUT);
pinMode(red,OUTPUT);
pinMode(green,OUTPUT);
digitalWrite(green,LOW);
digitalWrite(red,HIGH);
}

void loop(){
ora=Clock.getHour(h12, PM), DEC;
mins=Clock.getMinute(), DEC;
orario=ora+":"+mins;
byte i;
if (RC522.isCard()) {
if(verificaCodice(lettura())) {
rilevatore();
}
delay(delayRead);
}
if (orario=="21:56" && statoattivato==0) {
statoattivato=1;
rilevatore();
}
}

void rilevatore() {
if (attivo==false) {
attivo=true;
digitalWrite(red,LOW);
digitalWrite(green,HIGH);
while (attivo=true) {
if (sr04.Distance()<120)
tone(8,262,500);
if (RC522.isCard()) {
if (verificaCodice(lettura())) {
attivo=false;
digitalWrite(green,LOW);
digitalWrite(red,HIGH);
break;
}
}
}
}
}
boolean verificaCodice(String codiceLetto){
if(codiceLetto.equals(codiceAutorizzato)){
return true;
}
else{
return false;
}
}

String lettura(){
byte i;
RC522.readCardSerial();
String codiceLetto ="";
for(i = 0; i <= 4; i++) {
codiceLetto += String (RC522.serNum[i],HEX);
codiceLetto.toUpperCase();
}
return codiceLetto;
}
82) Arduino Smart Whellchair
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

SparkFun Dual H-Bridge motor


drivers L298
× 1
HC-05 Bluetooth Module
× 1

Ultrasonic Sensor - HC-SR04


(Generic)
× 1

DC motor (generic)
× 1

Rocker Switch, Non Illuminated

× 1

SparkFun Pushbutton switch 12mm

× 1

Buzzer

× 1

Breadboard (generic)

× 1

Li-Ion Battery 1000mAh

× 1
5 mm LED: Red

× 1

Jumper wires (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Objective
The objective of this project is to help physically challenged people. It
will basically very helpful for those who cannot able to walk.
Introduction
This is a simple prototype of Smart Wheelchair. The wheelchair is
multi functioned. One can use this wheelchair for various purposes.
This chair can be used as panic alarm. If the person needs instant help,
he/she can hit the panic alarm button so that someone can help him/her
immediately. This wheelchair also has a led light. So, anyone can roam
here and there when the surroundings has not enough light. Last but not
the least this wheelchair is also automatically identify the obstacles and
it makes decision to go with the obstacle free path.
Required Equipments
Arduino UNO
Motor Driver (Model:L298N)
Bluetooth Module (Model:HC-05)
Ultrasonic Sensor (Model:HC-SR04)
DC Motor
Lipo Battery(1000mAh)
Breadboard
LED
Push Button
Switch(ON/OFF)
Buzzer
Jumper Wire (Male to Male | Male to Female | Female to Female)
Connections
A) Motor Driver to Arduino
IN1 to Digital Pin 8
IN2 to Digital Pin 9
IN3 to Digital Pin 10
IN4 to Digital Pin 11
+12V to Lipo Battery Positive Lead
GND to Lipo Battery Negative Lead
+5V to VIN (Arduino)
B)Bluetooth Module to Arduino
+5V (Arduino) to +5V (Bluetooth)
GND (Arduino) to GND (Bluetooth)
RX (Arduino) to TX (Bluetooth)
TX (Arduino) to RX (Bluetooth)
C) Ultrasonic Sensor to Arduino
Trig Pin to Digital Pin 12
Echo Pin to Digital Pin 13
Trig Pin to Digital Pin 7
Echo Pin to Digital Pin 6
VCC to 5V
GND to GND
D) Other Connections
Led Light (Anode ) to Digital Pin 5 (Arduino)
Buzzer (Positive Lead) to Digital Pin 4 (Arduino)
Push Button (Positive Lead) to Digital Pin 3 (Arduino)
Bluetooth App Google Play Store Link
App Download Link: https://play.google.com/store/apps/details?
id=com.keuwl.arduinobluetooth
Bluetooth App Setting
Step-1
First download the app from the Google Play Store. I have given the
link of the app in the above (Bluetooth App Google Play Store Link)
Section.

Android App
Step-2
Edit a new panel for your Wheelchair controls

Edit a new panel for Wheelchair


Step-3
Now click on the "Connect" button and select "Bluetooth Classic"
option then click "Next" button to build up the bluetooth connection.

Click on Connect

Click on Bluetooth Classic


Step-4
After pairing between the application and "HC-05 Bluetooth Module"
and click "Done" button. Finally Click "Run" button to start working
with this app.

Click Done
Important Instructions
During the uploading the code on Arduino we need to pull down
the RX and TX connection from the Arduino.
Lipo Battery is very powerful battery. So, make sure that the each
connections are perfectly ok.
SCHEMATICS
CODE
int motorRightA = 8; //Right Motor-clockwise
int motorRightB = 9; //Right Motor-anticlockwise
int motorLeftA = 11; //Left Motor-clockwise
int motorLeftB = 10; //Left Motor-clockwise
int trigPin1 = 12; // Trig Pin
int echoPin1 = 13; // Echo Pin
int light = 5;
long duration1;
int distance1;
char bt = 0; //Bluetooth Control
int trigPin2 = 7; // Trig Pin
int echoPin2 = 6; // Echo Pin
long duration2;
int distance2;
int buzzer = 4;
int pushButton = 3;
void setup()
{
pinMode(motorRightA, OUTPUT);
pinMode(motorRightB, OUTPUT);
pinMode(motorRightB, OUTPUT);
pinMode(motorLeftB, OUTPUT);
pinMode(trigPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
pinMode(light, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(pushButton, INPUT_PULLUP);
Serial.begin(9600);
}
void loop()
{
//Light On Off
lightOnOff();
//Panic Button
panicSound();
// Right
digitalWrite(trigPin1, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin1, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin1, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration1 = pulseIn(echoPin1, HIGH);
// Calculating the distance
distance1 = duration1 * 0.034 / 2;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance1);
// Left
digitalWrite(trigPin2, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin2, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin2, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration2 = pulseIn(echoPin2, HIGH);
// Calculating the distance
distance2 = duration2 * 0.034 / 2;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance2);

if (distance1 <= 20 || distance2 <= 20) {


//Stop Wheel Chair
digitalWrite(motorRightA, LOW);
digitalWrite(motorRightB, LOW);
digitalWrite(motorLeftA, LOW);
digitalWrite(motorLeftB, LOW);
control();
}
else {
control(); // Call All the Control
}
}
// All the Controls of the Wheel Chair
void control() {
if (Serial.available() > 0)
{
bt = Serial.read();
if (bt == 'F') //move forwards
{
digitalWrite(motorRightA, HIGH);
digitalWrite(motorLeftA, HIGH);
}
else if (bt == 'B') //move backwards
{
digitalWrite(motorRightB, HIGH);
digitalWrite(motorLeftB, HIGH);
}
else if (bt == 'S') //stop!
{
digitalWrite(motorRightA, LOW);
digitalWrite(motorRightB, LOW);
digitalWrite(motorLeftA, LOW);
digitalWrite(motorLeftB, LOW);
}
else if (bt == 'R') //right
{
digitalWrite(motorRightA, LOW);
digitalWrite(motorRightB, LOW);
digitalWrite(motorLeftA, HIGH);
digitalWrite(motorLeftB, LOW);
}
else if (bt == 'L') //left
{
digitalWrite(motorRightA, HIGH);
digitalWrite(motorRightB, LOW);
digitalWrite(motorLeftA, LOW);
digitalWrite(motorLeftB, LOW);
}
else if (bt == 'I') //forward right
{
digitalWrite(motorRightA, HIGH);
digitalWrite(motorRightB, LOW);
digitalWrite(motorLeftA, LOW);
digitalWrite(motorLeftB, HIGH);
}
else if (bt == 'G') //forward left
{
digitalWrite(motorRightA, LOW);
digitalWrite(motorRightB, HIGH);
digitalWrite(motorLeftA, HIGH);
digitalWrite(motorLeftB, LOW);
}
}
}

void lightOnOff() {

if (bt == 'O') {
digitalWrite(light, HIGH);
}
else if (bt == 'o') {
digitalWrite(light, LOW);
}
}
void panicSound() {
int val = digitalRead(pushButton);
if (val == LOW) {
digitalWrite(buzzer, HIGH);
} else {
digitalWrite(buzzer, LOW);
}
}

83) Arduino Social Distancing Reminder


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO


Arduino Nano works better for
× 1
this, but I have used an Arduino
UNO.
Arduino Proto Shield
I used it, but it's optional.
× 1

Adafruit Mini Breadboard


× 1
Elegoo 16 x 2 LCD Display
× 1

Ultrasonic Sensor - HC-SR04


(Generic)
× 1

Touch sensor
You can also use a button, but × 1
you'll need a pull-down resistor.
NTC Thermistor
× 1

Resistor 10k ohm

× 1

Buzzer

× 1

Rotary potentiometer (generic)


This is to adjust the contrast of the
× 1
LCD.

Jumper wires (generic)

× 1
A transparent box to put everything
into
It needs to be transparent for you × 1
to be able to see the LCD and it
needs to be waterproof to light
rain
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

What is it?
Reasonably, the most reliable approach to slowing down the spread of
the coronavirus is to keep away from others; prevention is better than
cure. However, it would be irritating to turn around every thirty
seconds and look if someone was approaching you. It would be helpful
if there were a device that could warn others to keep away from you.
That is the purpose behind the project: to alert others to maintain a 2-
meter distance from you. It is a 2-in-1 as the thermistor is not only used
to add accuracy to the distance measurement (the speed of sound
changes depending on the temperature) but it also means that – by
using a button or a touch sensor to switch between the modes – it can
have two modes: alerting if someone comes close to you (Mode 1) and
measuring the temperature and the distance (Mode 2). The measuring
mode shows the temperature and the distance on the LCD.
How does it work?
The Arduino measures the temperature.
The temperature is used to calculate the distance with greater
accuracy.
If the Arduino is on Mode 1:
If the distance is between 2m and 1m, the LCD backlight lights up
and the LCD shows "Please keep away" and how far away the
person is.
If the distance is 1m - 50cm the backlight of the LCD flashes and the
LCD shows "Keep away"
If the distance is less than 50cm the backlight turns off and on twice
a second and the LCD shows "STAY AWAY!"
If the Arduino is on Mode 2, the LCD shows the distance on the top
and the temperature on the bottom of the screen.
To protect the components from the rain, I attached half a plastic bottle
which can be pushed up when there is rain.
It can be attached to (using two pieces of string) and be easily removed
from the bottom of a rucksack.

Mode 2
1m to 50cm
Closer than 50cm

2m to 1m

Protection from light rain

It can be attached to the bottom of a bag with string.


The touch sensor is used to switch between the modes.
The simplified algorithm
How do I build it?
Connect the components according to the circuit diagram below.
Once you have done that, import the libraries under the section named
'Code' – which you can do by (assuming you have opened the Arduino
IDE) going to 'Sketch' —> 'Include Library' —> 'Add .ZIP Library...'
and selecting the library (which should be a .zip file). Both libraries are
needed for the code to work.
Importing a library

Importing a library
SCHEMATICS

CODE
#include <HCSR04.h>
#include <LiquidCrystal.h>
#define trigPin 7
#define echoPin 6
#define buzzer 9
#define backlight 10

LiquidCrystal lcd(12, 11, 5, 4, 3, 8);


UltraSonicDistanceSensor distanceSensor(trigPin, echoPin);

int tempReading;
double tempK;
float tempC;
int rounded;
int temp_round;
volatile boolean modes = 0;
double distance;

void setup() {
lcd.begin(16, 2);
attachInterrupt(0, changeMode, FALLING);
pinMode(2, INPUT);
pinMode(buzzer, OUTPUT);
pinMode(backlight, OUTPUT);
digitalWrite(backlight, HIGH);
backlightOn();
}

void loop() {
tempReading = analogRead(A0);
tempK = log(10000.0 * ((1024.0 / tempReading - 1)));
tempK = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * tempK * tempK )) *
tempK );
tempC = tempK - 273.15;
distance = distanceSensor.measureDistanceCm(tempC);
temp_round = round(tempC);
if (modes == 1) {
backlightOn();
if (distance >= 300 || distance <= 0) {
rounded = 0;
lcd.clear();
lcd.print("Out of range");
lcd.setCursor(0, 1);
lcd.print("Temperature:" + String(temp_round) + " C");
}
else {
rounded = round(distance);
lcd.clear();
lcd.print("Distance: ");
lcd.print(rounded);
lcd.print(" cm");
lcd.setCursor(0, 1);
lcd.print("Temperature:" + String(temp_round) + " C");
}
} else {
if (distance >= 300 || distance <= 0) {
rounded = 0;
lcd.clear();
backlightOff();
}
else {
rounded = round(distance);
if (distance >= 200) {
backlightOff();
lcd.clear();
}
else if (distance <= 200 && distance > 100) {
backlightOn();
lcd.clear();
lcd.print("Please keep away");
lcd.setCursor(0, 1);
lcd.print("Distance:");
lcd.print(rounded);
lcd.print(" cm");
}
else if (distance <= 100 && distance > 50) {
backlightOn();
lcd.clear();
lcd.print("Keep away");
lcd.setCursor(0, 1);
lcd.print("Distance:");
lcd.print(rounded);
lcd.print(" cm");
delay(200);
buzz();
backlightOff();
delay(100);
unbuzz();
backlightOn();
delay(100);
}
else if (distance <= 50) {
backlightOn();
lcd.clear();
lcd.print("STAY AWAY!");
lcd.setCursor(0, 1);
lcd.print("Distance:");
lcd.print(rounded);
lcd.print(" cm");
delay(200);
buzz();
backlightOff();
delay(200);
unbuzz();
backlightOn();
delay(200);
buzz();
backlightOff();
delay(200);
unbuzz();
backlightOn();
}
}
}
delay(700);
}

void changeMode() {
modes = !modes;
}

void backlightOn() {
digitalWrite(backlight, HIGH);
}

void backlightOff() {
digitalWrite(backlight, LOW);
}

void buzz() {
digitalWrite(buzzer, HIGH);
}

void unbuzz() {
digitalWrite(buzzer, LOW);
}
84) Arduino RGB Goggles
COMPONENTS AND SUPPLIES
Arduino Nano R3

× 1

SparkFun RGB LED Breakout -


WS2812B
× 88

HC-05 Bluetooth Module

× 1

Battery, 3.7 V

× 1

Toggle Switch, On-On

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES

Arduino IDE

ABOUT THIS PROJECT

Hey! I have made a RGB Goggles using WS2812B LEDs and Arduino
Nano. The goggles have many animations they can be controlled using
a mobile app.The app can communicate with Arduino through
Bluetooth module. This goggles are lightweight.
SCHEMATICS

CODE
#include <FastLED.h>
#define LED_PIN 3
#define NUM_LEDS 88
#define LED_TYPE WS2812B
#define COLOR_ORDER RGB
#define BRIGHTNESS 255
#define UPDATES_PER_SECOND 100

#define kMatrixWidth 17
#define kMatrixHeight 6
#define kMatrixSerpentineLayout true
CRGBArray<NUM_LEDS> leds;

uint32_t x,y,v_time,hue_time,hxy;
uint8_t octaves=1;
uint8_t hue_octaves=3;
int xscale=57771;
int yscale=57771;
int hue_scale=1;
int time_speed=1111;
int hue_speed=31;
int x_speed=331;
int y_speed=1111;

CRGBPalette16 currentPalette;
TBlendType currentBlending;
extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

void setup()
{
Serial.begin(9600);
delay(1000);
FastLED.addLeds<NEOPIXEL,LED_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);

currentPalette = RainbowColors_p;
currentBlending = LINEARBLEND;

random16_set_seed(8934);
random16_add_entropy(analogRead(3));
hxy = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
x = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
y = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
v_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
hue_time = (uint32_t)((uint32_t)random16() << 16) + (uint32_t)random16();
}

void fadeall() { for(int i = 0; i < NUM_LEDS; i++) { leds[i].nscale8(250); } }

char ch;
void loop()
{
FastLED.clear();
FastLED.show();
if(Serial.available())
{
ch=Serial.read();
Serial.println(ch);
switch (ch)
{
case '1':
for(int i=0;i<10;i++)
{
leds[37] = CRGB(255, 0, 0);
leds[44] = CRGB(255, 0, 0);
FastLED.show();
delay(90);
FastLED.clear();
leds[20] = CRGB(255, 0, 0);
leds[30] = CRGB(255, 0, 0);
leds[36] = CRGB(255, 0, 0);
leds[38] = CRGB(255, 0, 0);
leds[43] = CRGB(255, 0, 0);
leds[45] = CRGB(255, 0, 0);
leds[51] = CRGB(255, 0, 0);
leds[58] = CRGB(255, 0, 0);
FastLED.show();
delay(90);
FastLED.clear();

leds[19] = CRGB(255, 0, 0);


leds[21] = CRGB(255, 0, 0);
leds[29] = CRGB(255, 0, 0);
leds[31] = CRGB(255, 0, 0);
leds[35] = CRGB(255, 0, 0);
leds[36] = CRGB(255, 0, 0);
leds[37] = CRGB(255, 0, 0);
leds[38] = CRGB(255, 0, 0);
leds[39] = CRGB(255, 0, 0);
leds[42] = CRGB(255, 0, 0);
leds[43] = CRGB(255, 0, 0);
leds[44] = CRGB(255, 0, 0);
leds[45] = CRGB(255, 0, 0);
leds[46] = CRGB(255, 0, 0);
leds[50] = CRGB(255, 0, 0);
leds[51] = CRGB(255, 0, 0);
leds[52] = CRGB(255, 0, 0);
leds[57] = CRGB(255, 0, 0);
leds[58] = CRGB(255, 0, 0);
leds[59] = CRGB(255, 0, 0);
leds[65] = CRGB(255, 0, 0);
leds[72] = CRGB(255, 0, 0);
FastLED.show();

delay(90);
FastLED.clear();

leds[1] = CRGB(255, 0, 0);


leds[2] = CRGB(255, 0, 0);
leds[4] = CRGB(255, 0, 0);
leds[5] = CRGB(255, 0, 0);
leds[6] = CRGB(0, 0, 0);
leds[11] = CRGB(255, 0, 0);
leds[12] = CRGB(255, 0, 0);
leds[14] = CRGB(255, 0, 0);
leds[15] = CRGB(255, 0, 0);
leds[17] = CRGB(255, 0, 0);
leds[18] = CRGB(255, 0, 0);
leds[19] = CRGB(255, 0, 0);
leds[20] = CRGB(255, 0, 0);
leds[21] = CRGB(255, 0, 0);
leds[22] = CRGB(255, 0, 0);
leds[23] = CRGB(255, 0, 0);
leds[27] = CRGB(255, 0, 0);
leds[28] = CRGB(255, 0, 0);
leds[29] = CRGB(255, 0, 0);
leds[30] = CRGB(255, 0, 0);
leds[31] = CRGB(255, 0, 0);
leds[32] = CRGB(255, 0, 0);
leds[33] = CRGB(255, 0, 0);
leds[34] = CRGB(255, 0, 0);
leds[35] = CRGB(255, 0, 0);
leds[36] = CRGB(255, 0, 0);
leds[37] = CRGB(255, 0, 0);
leds[38] = CRGB(255, 0, 0);
leds[39] = CRGB(255, 0, 0);
leds[40] = CRGB(255, 0, 0);
leds[41] = CRGB(255, 0, 0);
leds[42] = CRGB(255, 0, 0);
leds[43] = CRGB(255, 0, 0);
leds[44] = CRGB(255, 0, 0);
leds[45] = CRGB(255, 0, 0);
leds[46] = CRGB(255, 0, 0);
leds[47] = CRGB(255, 0, 0);
leds[49] = CRGB(255, 0, 0);
leds[50] = CRGB(255, 0, 0);
leds[51] = CRGB(255, 0, 0);
leds[52] = CRGB(255, 0, 0);
leds[53] = CRGB(255, 0, 0);
leds[56] = CRGB(255, 0, 0);
leds[57] = CRGB(255, 0, 0);
leds[58] = CRGB(255, 0, 0);
leds[59] = CRGB(255, 0, 0);
leds[60] = CRGB(255, 0, 0);
leds[64] = CRGB(255, 0, 0);
leds[65] = CRGB(255, 0, 0);
leds[66] = CRGB(255, 0, 0);
leds[71] = CRGB(255, 0, 0);
leds[72] = CRGB(255, 0, 0);
leds[73] = CRGB(255, 0, 0);
leds[79] = CRGB(255, 0, 0);
leds[84] = CRGB(255, 0, 0);
FastLED.show();
delay(90);
FastLED.clear();

leds[19] = CRGB(255, 0, 0);


leds[21] = CRGB(255, 0, 0);
leds[29] = CRGB(255, 0, 0);
leds[31] = CRGB(255, 0, 0);
leds[35] = CRGB(255, 0, 0);
leds[36] = CRGB(255, 0, 0);
leds[37] = CRGB(255, 0, 0);
leds[38] = CRGB(255, 0, 0);
leds[39] = CRGB(255, 0, 0);
leds[42] = CRGB(255, 0, 0);
leds[43] = CRGB(255, 0, 0);
leds[44] = CRGB(255, 0, 0);
leds[45] = CRGB(255, 0, 0);
leds[46] = CRGB(255, 0, 0);
leds[50] = CRGB(255, 0, 0);
leds[51] = CRGB(255, 0, 0);
leds[52] = CRGB(255, 0, 0);
leds[57] = CRGB(255, 0, 0);
leds[58] = CRGB(255, 0, 0);
leds[59] = CRGB(255, 0, 0);
leds[65] = CRGB(255, 0, 0);
leds[72] = CRGB(255, 0, 0);
FastLED.show();

delay(90);
FastLED.clear();
leds[20] = CRGB(255, 0, 0);
leds[30] = CRGB(255, 0, 0);
leds[36] = CRGB(255, 0, 0);
leds[38] = CRGB(255, 0, 0);
leds[43] = CRGB(255, 0, 0);
leds[45] = CRGB(255, 0, 0);
leds[51] = CRGB(255, 0, 0);
leds[58] = CRGB(255, 0, 0);
FastLED.show();
delay(90);
FastLED.clear();
}
break;

case '2':
for(int i=0;i<5;i++)
{
leds[36] = CRGB(255, 0, 187);
leds[37] = CRGB(255, 0, 187);
leds[44] = CRGB(255, 0, 187);
leds[45] = CRGB(255, 0, 187);
leds[50] = CRGB(255, 0, 187);
leds[51] = CRGB(255, 0, 187);
leds[58] = CRGB(255, 0, 187);
leds[59] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();

leds[19] = CRGB(255, 0, 187);


leds[20] = CRGB(255, 0, 187);
leds[30] = CRGB(255, 0, 187);
leds[31] = CRGB(255, 0, 187);
leds[35] = CRGB(255, 0, 187);
leds[38] = CRGB(255, 0, 187);
leds[43] = CRGB(255, 0, 187);
leds[46] = CRGB(255, 0, 187);
leds[49] = CRGB(255, 0, 187);
leds[52] = CRGB(255, 0, 187);
leds[57] = CRGB(255, 0, 187);
leds[60] = CRGB(255, 0, 187);
leds[64] = CRGB(255, 0, 187);
leds[65] = CRGB(255, 0, 187);
leds[72] = CRGB(255, 0, 187);
leds[73] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();

leds[0] = CRGB(0, 0, 0);


leds[1] = CRGB(255, 0, 187);
leds[2] = CRGB(255, 0, 187);
leds[3] = CRGB(255, 0, 187);
leds[4] = CRGB(255, 0, 187);
leds[12] = CRGB(255, 0, 187);
leds[13] = CRGB(255, 0, 187);
leds[14] = CRGB(255, 0, 187);
leds[15] = CRGB(255, 0, 187);
leds[17] = CRGB(255, 0, 187);
leds[22] = CRGB(255, 0, 187);
leds[28] = CRGB(255, 0, 187);
leds[33] = CRGB(255, 0, 187);
leds[34] = CRGB(255, 0, 187);
leds[39] = CRGB(255, 0, 187);
leds[42] = CRGB(255, 0, 187);
leds[47] = CRGB(255, 0, 187);
leds[48] = CRGB(255, 0, 187);
leds[53] = CRGB(255, 0, 187);
leds[56] = CRGB(255, 0, 187);
leds[61] = CRGB(255, 0, 187);
leds[62] = CRGB(255, 0, 187);
leds[67] = CRGB(255, 0, 187);
leds[70] = CRGB(255, 0, 187);
leds[75] = CRGB(255, 0, 187);
leds[77] = CRGB(255, 0, 187);
leds[78] = CRGB(255, 0, 187);
leds[79] = CRGB(255, 0, 187);
leds[80] = CRGB(255, 0, 187);
leds[83] = CRGB(255, 0, 187);
leds[84] = CRGB(255, 0, 187);
leds[85] = CRGB(255, 0, 187);
leds[86] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();

leds[0] = CRGB(0, 0, 0);


leds[1] = CRGB(255, 0, 187);
leds[2] = CRGB(255, 0, 187);
leds[3] = CRGB(255, 0, 187);
leds[4] = CRGB(255, 0, 187);
leds[12] = CRGB(255, 0, 187);
leds[13] = CRGB(255, 0, 187);
leds[14] = CRGB(255, 0, 187);
leds[15] = CRGB(255, 0, 187);
leds[17] = CRGB(255, 0, 187);
leds[22] = CRGB(255, 0, 187);
leds[28] = CRGB(255, 0, 187);
leds[33] = CRGB(255, 0, 187);
leds[34] = CRGB(255, 0, 187);
leds[39] = CRGB(255, 0, 187);
leds[42] = CRGB(255, 0, 187);
leds[47] = CRGB(255, 0, 187);
leds[48] = CRGB(255, 0, 187);
leds[53] = CRGB(255, 0, 187);
leds[56] = CRGB(255, 0, 187);
leds[61] = CRGB(255, 0, 187);
leds[62] = CRGB(255, 0, 187);
leds[67] = CRGB(255, 0, 187);
leds[70] = CRGB(255, 0, 187);
leds[75] = CRGB(255, 0, 187);
leds[77] = CRGB(255, 0, 187);
leds[78] = CRGB(255, 0, 187);
leds[79] = CRGB(255, 0, 187);
leds[80] = CRGB(255, 0, 187);
leds[83] = CRGB(255, 0, 187);
leds[84] = CRGB(255, 0, 187);
leds[85] = CRGB(255, 0, 187);
leds[86] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();

leds[19] = CRGB(255, 0, 187);


leds[20] = CRGB(255, 0, 187);
leds[30] = CRGB(255, 0, 187);
leds[31] = CRGB(255, 0, 187);
leds[35] = CRGB(255, 0, 187);
leds[38] = CRGB(255, 0, 187);
leds[43] = CRGB(255, 0, 187);
leds[46] = CRGB(255, 0, 187);
leds[49] = CRGB(255, 0, 187);
leds[52] = CRGB(255, 0, 187);
leds[57] = CRGB(255, 0, 187);
leds[60] = CRGB(255, 0, 187);
leds[64] = CRGB(255, 0, 187);
leds[65] = CRGB(255, 0, 187);
leds[72] = CRGB(255, 0, 187);
leds[73] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();

leds[36] = CRGB(255, 0, 187);


leds[37] = CRGB(255, 0, 187);
leds[44] = CRGB(255, 0, 187);
leds[45] = CRGB(255, 0, 187);
leds[50] = CRGB(255, 0, 187);
leds[51] = CRGB(255, 0, 187);
leds[58] = CRGB(255, 0, 187);
leds[59] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();
}
break;

case '3':
for(int i=0;i<5;i++)
{
leds[0] = CRGB(255, 0, 187);
leds[1] = CRGB(255, 0, 187);
leds[2] = CRGB(255, 0, 187);
leds[3] = CRGB(255, 0, 187);
leds[4] = CRGB(255, 0, 187);
leds[5] = CRGB(255, 0, 187);
leds[6] = CRGB(255, 0, 187);
leds[7] = CRGB(255, 0, 187);
leds[8] = CRGB(255, 0, 187);
leds[9] = CRGB(255, 0, 187);
leds[10] = CRGB(255, 0, 187);
leds[11] = CRGB(255, 0, 187);
leds[12] = CRGB(255, 0, 187);
leds[13] = CRGB(255, 0, 187);
leds[14] = CRGB(255, 0, 187);
leds[15] = CRGB(255, 0, 187);
leds[16] = CRGB(255, 0, 187);
leds[17] = CRGB(255, 0, 187);
leds[18] = CRGB(255, 161, 0);
leds[19] = CRGB(255, 161, 0);
leds[20] = CRGB(255, 161, 0);
leds[21] = CRGB(255, 161, 0);
leds[22] = CRGB(255, 161, 0);
leds[23] = CRGB(255, 0, 187);
leds[24] = CRGB(255, 0, 187);
leds[25] = CRGB(255, 0, 187);
leds[26] = CRGB(255, 0, 187);
leds[27] = CRGB(255, 0, 187);
leds[28] = CRGB(255, 161, 0);
leds[29] = CRGB(255, 161, 0);
leds[30] = CRGB(255, 161, 0);
leds[31] = CRGB(255, 161, 0);
leds[32] = CRGB(255, 161, 0);
leds[33] = CRGB(255, 0, 187);
leds[34] = CRGB(255, 0, 187);
leds[35] = CRGB(255, 161, 0);
leds[36] = CRGB(0, 255, 255);
leds[37] = CRGB(0, 255, 255);
leds[38] = CRGB(0, 255, 255);
leds[39] = CRGB(255, 161, 0);
leds[40] = CRGB(255, 0, 187);
leds[41] = CRGB(255, 0, 187);
leds[42] = CRGB(255, 161, 0);
leds[43] = CRGB(0, 255, 255);
leds[44] = CRGB(0, 255, 255);
leds[45] = CRGB(0, 255, 255);
leds[46] = CRGB(255, 161, 0);
leds[47] = CRGB(255, 0, 187);
leds[48] = CRGB(255, 0, 187);
leds[49] = CRGB(255, 161, 0);
leds[50] = CRGB(0, 255, 255);
leds[51] = CRGB(0, 255, 255);
leds[52] = CRGB(0, 255, 255);
leds[53] = CRGB(255, 161, 0);
leds[54] = CRGB(255, 0, 187);
leds[55] = CRGB(255, 0, 187);
leds[56] = CRGB(255, 161, 0);
leds[57] = CRGB(0, 255, 255);
leds[58] = CRGB(0, 255, 255);
leds[59] = CRGB(0, 255, 255);
leds[60] = CRGB(255, 161, 0);
leds[61] = CRGB(255, 0, 187);
leds[62] = CRGB(255, 0, 187);
leds[63] = CRGB(255, 161, 0);
leds[64] = CRGB(255, 161, 0);
leds[65] = CRGB(255, 161, 0);
leds[66] = CRGB(255, 161, 0);
leds[67] = CRGB(255, 161, 0);
leds[68] = CRGB(255, 0, 187);
leds[69] = CRGB(255, 0, 187);
leds[70] = CRGB(255, 161, 0);
leds[71] = CRGB(255, 161, 0);
leds[72] = CRGB(255, 161, 0);
leds[73] = CRGB(255, 161, 0);
leds[74] = CRGB(255, 161, 0);
leds[75] = CRGB(255, 0, 187);
leds[76] = CRGB(255, 0, 187);
leds[77] = CRGB(255, 0, 187);
leds[78] = CRGB(255, 0, 187);
leds[79] = CRGB(255, 0, 187);
leds[80] = CRGB(255, 0, 187);
leds[81] = CRGB(255, 0, 187);
leds[82] = CRGB(255, 0, 187);
leds[83] = CRGB(255, 0, 187);
leds[84] = CRGB(255, 0, 187);
leds[85] = CRGB(255, 0, 187);
leds[86] = CRGB(255, 0, 187);
leds[87] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();

leds[0] = CRGB(255, 164, 0);


leds[1] = CRGB(255, 164, 0);
leds[2] = CRGB(255, 164, 0);
leds[3] = CRGB(255, 164, 0);
leds[4] = CRGB(255, 164, 0);
leds[5] = CRGB(255, 164, 0);
leds[6] = CRGB(255, 164, 0);
leds[7] = CRGB(255, 164, 0);
leds[8] = CRGB(255, 164, 0);
leds[9] = CRGB(255, 164, 0);
leds[10] = CRGB(255, 164, 0);
leds[11] = CRGB(255, 164, 0);
leds[12] = CRGB(255, 164, 0);
leds[13] = CRGB(255, 164, 0);
leds[14] = CRGB(255, 164, 0);
leds[15] = CRGB(255, 164, 0);
leds[16] = CRGB(255, 164, 0);
leds[17] = CRGB(255, 164, 0);
leds[18] = CRGB(0, 255, 255);
leds[19] = CRGB(0, 255, 255);
leds[20] = CRGB(0, 255, 255);
leds[21] = CRGB(0, 255, 255);
leds[22] = CRGB(0, 255, 255);
leds[23] = CRGB(255, 164, 0);
leds[24] = CRGB(255, 164, 0);
leds[25] = CRGB(255, 164, 0);
leds[26] = CRGB(255, 164, 0);
leds[27] = CRGB(255, 164, 0);
leds[28] = CRGB(0, 255, 255);
leds[29] = CRGB(0, 255, 255);
leds[30] = CRGB(0, 255, 255);
leds[31] = CRGB(0, 255, 255);
leds[32] = CRGB(0, 255, 255);
leds[33] = CRGB(255, 164, 0);
leds[34] = CRGB(255, 164, 0);
leds[35] = CRGB(0, 255, 255);
leds[36] = CRGB(255, 0, 177);
leds[37] = CRGB(255, 0, 177);
leds[38] = CRGB(255, 0, 177);
leds[39] = CRGB(0, 255, 255);
leds[40] = CRGB(255, 164, 0);
leds[41] = CRGB(255, 146, 0);
leds[42] = CRGB(0, 255, 255);
leds[43] = CRGB(255, 0, 177);
leds[44] = CRGB(255, 0, 177);
leds[45] = CRGB(255, 0, 177);
leds[46] = CRGB(0, 255, 255);
leds[47] = CRGB(255, 146, 0);
leds[48] = CRGB(255, 146, 0);
leds[49] = CRGB(0, 255, 255);
leds[50] = CRGB(255, 0, 177);
leds[51] = CRGB(255, 0, 177);
leds[52] = CRGB(255, 0, 177);
leds[53] = CRGB(0, 255, 255);
leds[54] = CRGB(255, 164, 0);
leds[55] = CRGB(255, 164, 0);
leds[56] = CRGB(0, 255, 255);
leds[57] = CRGB(255, 0, 177);
leds[58] = CRGB(255, 0, 177);
leds[59] = CRGB(255, 0, 177);
leds[60] = CRGB(0, 255, 255);
leds[61] = CRGB(255, 164, 0);
leds[62] = CRGB(255, 164, 0);
leds[63] = CRGB(0, 255, 255);
leds[64] = CRGB(0, 255, 255);
leds[65] = CRGB(0, 255, 255);
leds[66] = CRGB(0, 255, 255);
leds[67] = CRGB(0, 255, 255);
leds[68] = CRGB(255, 164, 0);
leds[69] = CRGB(255, 164, 0);
leds[70] = CRGB(0, 255, 255);
leds[71] = CRGB(0, 255, 255);
leds[72] = CRGB(0, 255, 255);
leds[73] = CRGB(0, 255, 255);
leds[74] = CRGB(0, 255, 255);
leds[75] = CRGB(255, 164, 0);
leds[76] = CRGB(255, 164, 0);
leds[77] = CRGB(255, 164, 0);
leds[78] = CRGB(255, 164, 0);
leds[79] = CRGB(255, 164, 0);
leds[80] = CRGB(255, 164, 0);
leds[81] = CRGB(255, 164, 0);
leds[82] = CRGB(255, 164, 0);
leds[83] = CRGB(255, 164, 0);
leds[84] = CRGB(255, 164, 0);
leds[85] = CRGB(255, 164, 0);
leds[86] = CRGB(255, 164, 0);
leds[87] = CRGB(255, 164, 0);
FastLED.show();
delay(90);
FastLED.clear();

leds[0] = CRGB(0, 255, 255);


leds[1] = CRGB(0, 255, 255);
leds[2] = CRGB(0, 255, 255);
leds[3] = CRGB(0, 255, 255);
leds[4] = CRGB(0, 255, 255);
leds[5] = CRGB(0, 255, 255);
leds[6] = CRGB(0, 255, 255);
leds[7] = CRGB(0, 255, 255);
leds[8] = CRGB(0, 255, 255);
leds[9] = CRGB(0, 255, 255);
leds[10] = CRGB(0, 255, 255);
leds[11] = CRGB(0, 255, 255);
leds[12] = CRGB(0, 255, 255);
leds[13] = CRGB(0, 255, 255);
leds[14] = CRGB(0, 255, 255);
leds[15] = CRGB(0, 255, 255);
leds[16] = CRGB(0, 255, 255);
leds[17] = CRGB(0, 255, 255);
leds[18] = CRGB(255, 0, 208);
leds[19] = CRGB(255, 0, 208);
leds[20] = CRGB(255, 0, 180);
leds[21] = CRGB(255, 0, 180);
leds[22] = CRGB(255, 0, 180);
leds[23] = CRGB(0, 255, 255);
leds[24] = CRGB(0, 255, 255);
leds[25] = CRGB(0, 255, 255);
leds[26] = CRGB(0, 255, 255);
leds[27] = CRGB(0, 255, 255);
leds[28] = CRGB(255, 0, 208);
leds[29] = CRGB(255, 0, 208);
leds[30] = CRGB(255, 0, 180);
leds[31] = CRGB(255, 0, 180);
leds[32] = CRGB(255, 0, 180);
leds[33] = CRGB(0, 255, 255);
leds[34] = CRGB(0, 255, 255);
leds[35] = CRGB(255, 0, 180);
leds[36] = CRGB(255, 148, 0);
leds[37] = CRGB(255, 148, 0);
leds[38] = CRGB(255, 148, 0);
leds[39] = CRGB(255, 0, 208);
leds[40] = CRGB(0, 255, 255);
leds[41] = CRGB(0, 255, 255);
leds[42] = CRGB(255, 0, 180);
leds[43] = CRGB(255, 148, 0);
leds[44] = CRGB(255, 148, 0);
leds[45] = CRGB(255, 148, 0);
leds[46] = CRGB(255, 0, 180);
leds[47] = CRGB(0, 255, 255);
leds[48] = CRGB(0, 255, 255);
leds[49] = CRGB(255, 0, 208);
leds[50] = CRGB(255, 148, 0);
leds[51] = CRGB(255, 148, 0);
leds[52] = CRGB(255, 148, 0);
leds[53] = CRGB(255, 0, 180);
leds[54] = CRGB(0, 255, 255);
leds[55] = CRGB(0, 255, 255);
leds[56] = CRGB(255, 0, 180);
leds[57] = CRGB(255, 148, 0);
leds[58] = CRGB(255, 148, 0);
leds[59] = CRGB(255, 148, 0);
leds[60] = CRGB(255, 0, 180);
leds[61] = CRGB(0, 255, 255);
leds[62] = CRGB(0, 255, 255);
leds[63] = CRGB(255, 0, 180);
leds[64] = CRGB(255, 0, 180);
leds[65] = CRGB(255, 0, 180);
leds[66] = CRGB(255, 0, 180);
leds[67] = CRGB(255, 0, 180);
leds[68] = CRGB(0, 255, 255);
leds[69] = CRGB(0, 255, 255);
leds[70] = CRGB(255, 0, 180);
leds[71] = CRGB(255, 0, 180);
leds[72] = CRGB(255, 0, 180);
leds[73] = CRGB(255, 0, 180);
leds[74] = CRGB(255, 0, 180);
leds[75] = CRGB(0, 255, 255);
leds[76] = CRGB(0, 255, 255);
leds[77] = CRGB(0, 255, 255);
leds[78] = CRGB(0, 255, 255);
leds[79] = CRGB(0, 255, 255);
leds[80] = CRGB(0, 255, 255);
leds[81] = CRGB(0, 255, 255);
leds[82] = CRGB(0, 255, 255);
leds[83] = CRGB(0, 255, 255);
leds[84] = CRGB(0, 255, 255);
leds[85] = CRGB(0, 255, 255);
leds[86] = CRGB(0, 255, 255);
leds[87] = CRGB(0, 255, 255);
FastLED.show();
delay(90);
FastLED.clear();

leds[0] = CRGB(0, 255, 255);


leds[1] = CRGB(0, 255, 255);
leds[2] = CRGB(0, 255, 255);
leds[3] = CRGB(0, 255, 255);
leds[4] = CRGB(0, 255, 255);
leds[5] = CRGB(0, 255, 255);
leds[6] = CRGB(0, 255, 255);
leds[7] = CRGB(0, 255, 255);
leds[8] = CRGB(0, 255, 255);
leds[9] = CRGB(0, 255, 255);
leds[10] = CRGB(0, 255, 255);
leds[11] = CRGB(0, 255, 255);
leds[12] = CRGB(0, 255, 255);
leds[13] = CRGB(0, 255, 255);
leds[14] = CRGB(0, 255, 255);
leds[15] = CRGB(0, 255, 255);
leds[16] = CRGB(0, 255, 255);
leds[17] = CRGB(0, 255, 255);
leds[18] = CRGB(255, 0, 208);
leds[19] = CRGB(255, 0, 208);
leds[20] = CRGB(255, 0, 180);
leds[21] = CRGB(255, 0, 180);
leds[22] = CRGB(255, 0, 180);
leds[23] = CRGB(0, 255, 255);
leds[24] = CRGB(0, 255, 255);
leds[25] = CRGB(0, 255, 255);
leds[26] = CRGB(0, 255, 255);
leds[27] = CRGB(0, 255, 255);
leds[28] = CRGB(255, 0, 208);
leds[29] = CRGB(255, 0, 208);
leds[30] = CRGB(255, 0, 180);
leds[31] = CRGB(255, 0, 180);
leds[32] = CRGB(255, 0, 180);
leds[33] = CRGB(0, 255, 255);
leds[34] = CRGB(0, 255, 255);
leds[35] = CRGB(255, 0, 180);
leds[36] = CRGB(255, 148, 0);
leds[37] = CRGB(255, 148, 0);
leds[38] = CRGB(255, 148, 0);
leds[39] = CRGB(255, 0, 208);
leds[40] = CRGB(0, 255, 255);
leds[41] = CRGB(0, 255, 255);
leds[42] = CRGB(255, 0, 180);
leds[43] = CRGB(255, 148, 0);
leds[44] = CRGB(255, 148, 0);
leds[45] = CRGB(255, 148, 0);
leds[46] = CRGB(255, 0, 180);
leds[47] = CRGB(0, 255, 255);
leds[48] = CRGB(0, 255, 255);
leds[49] = CRGB(255, 0, 208);
leds[50] = CRGB(255, 148, 0);
leds[51] = CRGB(255, 148, 0);
leds[52] = CRGB(255, 148, 0);
leds[53] = CRGB(255, 0, 180);
leds[54] = CRGB(0, 255, 255);
leds[55] = CRGB(0, 255, 255);
leds[56] = CRGB(255, 0, 180);
leds[57] = CRGB(255, 148, 0);
leds[58] = CRGB(255, 148, 0);
leds[59] = CRGB(255, 148, 0);
leds[60] = CRGB(255, 0, 180);
leds[61] = CRGB(0, 255, 255);
leds[62] = CRGB(0, 255, 255);
leds[63] = CRGB(255, 0, 180);
leds[64] = CRGB(255, 0, 180);
leds[65] = CRGB(255, 0, 180);
leds[66] = CRGB(255, 0, 180);
leds[67] = CRGB(255, 0, 180);
leds[68] = CRGB(0, 255, 255);
leds[69] = CRGB(0, 255, 255);
leds[70] = CRGB(255, 0, 180);
leds[71] = CRGB(255, 0, 180);
leds[72] = CRGB(255, 0, 180);
leds[73] = CRGB(255, 0, 180);
leds[74] = CRGB(255, 0, 180);
leds[75] = CRGB(0, 255, 255);
leds[76] = CRGB(0, 255, 255);
leds[77] = CRGB(0, 255, 255);
leds[78] = CRGB(0, 255, 255);
leds[79] = CRGB(0, 255, 255);
leds[80] = CRGB(0, 255, 255);
leds[81] = CRGB(0, 255, 255);
leds[82] = CRGB(0, 255, 255);
leds[83] = CRGB(0, 255, 255);
leds[84] = CRGB(0, 255, 255);
leds[85] = CRGB(0, 255, 255);
leds[86] = CRGB(0, 255, 255);
leds[87] = CRGB(0, 255, 255);
FastLED.show();
delay(90);
FastLED.clear();

leds[0] = CRGB(255, 164, 0);


leds[1] = CRGB(255, 164, 0);
leds[2] = CRGB(255, 164, 0);
leds[3] = CRGB(255, 164, 0);
leds[4] = CRGB(255, 164, 0);
leds[5] = CRGB(255, 164, 0);
leds[6] = CRGB(255, 164, 0);
leds[7] = CRGB(255, 164, 0);
leds[8] = CRGB(255, 164, 0);
leds[9] = CRGB(255, 164, 0);
leds[10] = CRGB(255, 164, 0);
leds[11] = CRGB(255, 164, 0);
leds[12] = CRGB(255, 164, 0);
leds[13] = CRGB(255, 164, 0);
leds[14] = CRGB(255, 164, 0);
leds[15] = CRGB(255, 164, 0);
leds[16] = CRGB(255, 164, 0);
leds[17] = CRGB(255, 164, 0);
leds[18] = CRGB(0, 255, 255);
leds[19] = CRGB(0, 255, 255);
leds[20] = CRGB(0, 255, 255);
leds[21] = CRGB(0, 255, 255);
leds[22] = CRGB(0, 255, 255);
leds[23] = CRGB(255, 164, 0);
leds[24] = CRGB(255, 164, 0);
leds[25] = CRGB(255, 164, 0);
leds[26] = CRGB(255, 164, 0);
leds[27] = CRGB(255, 164, 0);
leds[28] = CRGB(0, 255, 255);
leds[29] = CRGB(0, 255, 255);
leds[30] = CRGB(0, 255, 255);
leds[31] = CRGB(0, 255, 255);
leds[32] = CRGB(0, 255, 255);
leds[33] = CRGB(255, 164, 0);
leds[34] = CRGB(255, 164, 0);
leds[35] = CRGB(0, 255, 255);
leds[36] = CRGB(255, 0, 177);
leds[37] = CRGB(255, 0, 177);
leds[38] = CRGB(255, 0, 177);
leds[39] = CRGB(0, 255, 255);
leds[40] = CRGB(255, 164, 0);
leds[41] = CRGB(255, 146, 0);
leds[42] = CRGB(0, 255, 255);
leds[43] = CRGB(255, 0, 177);
leds[44] = CRGB(255, 0, 177);
leds[45] = CRGB(255, 0, 177);
leds[46] = CRGB(0, 255, 255);
leds[47] = CRGB(255, 146, 0);
leds[48] = CRGB(255, 146, 0);
leds[49] = CRGB(0, 255, 255);
leds[50] = CRGB(255, 0, 177);
leds[51] = CRGB(255, 0, 177);
leds[52] = CRGB(255, 0, 177);
leds[53] = CRGB(0, 255, 255);
leds[54] = CRGB(255, 164, 0);
leds[55] = CRGB(255, 164, 0);
leds[56] = CRGB(0, 255, 255);
leds[57] = CRGB(255, 0, 177);
leds[58] = CRGB(255, 0, 177);
leds[59] = CRGB(255, 0, 177);
leds[60] = CRGB(0, 255, 255);
leds[61] = CRGB(255, 164, 0);
leds[62] = CRGB(255, 164, 0);
leds[63] = CRGB(0, 255, 255);
leds[64] = CRGB(0, 255, 255);
leds[65] = CRGB(0, 255, 255);
leds[66] = CRGB(0, 255, 255);
leds[67] = CRGB(0, 255, 255);
leds[68] = CRGB(255, 164, 0);
leds[69] = CRGB(255, 164, 0);
leds[70] = CRGB(0, 255, 255);
leds[71] = CRGB(0, 255, 255);
leds[72] = CRGB(0, 255, 255);
leds[73] = CRGB(0, 255, 255);
leds[74] = CRGB(0, 255, 255);
leds[75] = CRGB(255, 164, 0);
leds[76] = CRGB(255, 164, 0);
leds[77] = CRGB(255, 164, 0);
leds[78] = CRGB(255, 164, 0);
leds[79] = CRGB(255, 164, 0);
leds[80] = CRGB(255, 164, 0);
leds[81] = CRGB(255, 164, 0);
leds[82] = CRGB(255, 164, 0);
leds[83] = CRGB(255, 164, 0);
leds[84] = CRGB(255, 164, 0);
leds[85] = CRGB(255, 164, 0);
leds[86] = CRGB(255, 164, 0);
leds[87] = CRGB(255, 164, 0);
FastLED.show();
delay(90);
FastLED.clear();
leds[0] = CRGB(255, 0, 187);
leds[1] = CRGB(255, 0, 187);
leds[2] = CRGB(255, 0, 187);
leds[3] = CRGB(255, 0, 187);
leds[4] = CRGB(255, 0, 187);
leds[5] = CRGB(255, 0, 187);
leds[6] = CRGB(255, 0, 187);
leds[7] = CRGB(255, 0, 187);
leds[8] = CRGB(255, 0, 187);
leds[9] = CRGB(255, 0, 187);
leds[10] = CRGB(255, 0, 187);
leds[11] = CRGB(255, 0, 187);
leds[12] = CRGB(255, 0, 187);
leds[13] = CRGB(255, 0, 187);
leds[14] = CRGB(255, 0, 187);
leds[15] = CRGB(255, 0, 187);
leds[16] = CRGB(255, 0, 187);
leds[17] = CRGB(255, 0, 187);
leds[18] = CRGB(255, 161, 0);
leds[19] = CRGB(255, 161, 0);
leds[20] = CRGB(255, 161, 0);
leds[21] = CRGB(255, 161, 0);
leds[22] = CRGB(255, 161, 0);
leds[23] = CRGB(255, 0, 187);
leds[24] = CRGB(255, 0, 187);
leds[25] = CRGB(255, 0, 187);
leds[26] = CRGB(255, 0, 187);
leds[27] = CRGB(255, 0, 187);
leds[28] = CRGB(255, 161, 0);
leds[29] = CRGB(255, 161, 0);
leds[30] = CRGB(255, 161, 0);
leds[31] = CRGB(255, 161, 0);
leds[32] = CRGB(255, 161, 0);
leds[33] = CRGB(255, 0, 187);
leds[34] = CRGB(255, 0, 187);
leds[35] = CRGB(255, 161, 0);
leds[36] = CRGB(0, 255, 255);
leds[37] = CRGB(0, 255, 255);
leds[38] = CRGB(0, 255, 255);
leds[39] = CRGB(255, 161, 0);
leds[40] = CRGB(255, 0, 187);
leds[41] = CRGB(255, 0, 187);
leds[42] = CRGB(255, 161, 0);
leds[43] = CRGB(0, 255, 255);
leds[44] = CRGB(0, 255, 255);
leds[45] = CRGB(0, 255, 255);
leds[46] = CRGB(255, 161, 0);
leds[47] = CRGB(255, 0, 187);
leds[48] = CRGB(255, 0, 187);
leds[49] = CRGB(255, 161, 0);
leds[50] = CRGB(0, 255, 255);
leds[51] = CRGB(0, 255, 255);
leds[52] = CRGB(0, 255, 255);
leds[53] = CRGB(255, 161, 0);
leds[54] = CRGB(255, 0, 187);
leds[55] = CRGB(255, 0, 187);
leds[56] = CRGB(255, 161, 0);
leds[57] = CRGB(0, 255, 255);
leds[58] = CRGB(0, 255, 255);
leds[59] = CRGB(0, 255, 255);
leds[60] = CRGB(255, 161, 0);
leds[61] = CRGB(255, 0, 187);
leds[62] = CRGB(255, 0, 187);
leds[63] = CRGB(255, 161, 0);
leds[64] = CRGB(255, 161, 0);
leds[65] = CRGB(255, 161, 0);
leds[66] = CRGB(255, 161, 0);
leds[67] = CRGB(255, 161, 0);
leds[68] = CRGB(255, 0, 187);
leds[69] = CRGB(255, 0, 187);
leds[70] = CRGB(255, 161, 0);
leds[71] = CRGB(255, 161, 0);
leds[72] = CRGB(255, 161, 0);
leds[73] = CRGB(255, 161, 0);
leds[74] = CRGB(255, 161, 0);
leds[75] = CRGB(255, 0, 187);
leds[76] = CRGB(255, 0, 187);
leds[77] = CRGB(255, 0, 187);
leds[78] = CRGB(255, 0, 187);
leds[79] = CRGB(255, 0, 187);
leds[80] = CRGB(255, 0, 187);
leds[81] = CRGB(255, 0, 187);
leds[82] = CRGB(255, 0, 187);
leds[83] = CRGB(255, 0, 187);
leds[84] = CRGB(255, 0, 187);
leds[85] = CRGB(255, 0, 187);
leds[86] = CRGB(255, 0, 187);
leds[87] = CRGB(255, 0, 187);
FastLED.show();
delay(90);
FastLED.clear();
}
break;

case '4':

leds[2] = CRGB(0, 183, 255);


leds[3] = CRGB(0, 183, 255);
leds[13] = CRGB(0, 183, 255);
leds[14] = CRGB(0, 183, 255);
leds[17] = CRGB(0, 183, 255);
leds[18] = CRGB(0, 183, 255);
leds[19] = CRGB(0, 183, 255);
leds[20] = CRGB(0, 183, 255);
leds[21] = CRGB(0, 183, 255);
leds[28] = CRGB(0, 183, 255);
leds[29] = CRGB(0, 183, 255);
leds[30] = CRGB(0, 183, 255);
leds[31] = CRGB(0, 183, 255);
leds[32] = CRGB(0, 183, 255);
leds[34] = CRGB(0, 183, 255);
leds[36] = CRGB(0, 183, 255);
leds[37] = CRGB(0, 183, 255);
leds[42] = CRGB(0, 183, 255);
leds[44] = CRGB(0, 183, 255);
leds[45] = CRGB(0, 183, 255);
leds[48] = CRGB(0, 183, 255);
leds[49] = CRGB(0, 183, 255);
leds[50] = CRGB(0, 183, 255);
leds[51] = CRGB(0, 183, 255);
leds[52] = CRGB(0, 183, 255);
leds[53] = CRGB(0, 183, 255);
leds[56] = CRGB(0, 183, 255);
leds[57] = CRGB(0, 183, 255);
leds[58] = CRGB(0, 183, 255);
leds[59] = CRGB(0, 183, 255);
leds[60] = CRGB(0, 183, 255);
leds[64] = CRGB(0, 183, 255);
leds[65] = CRGB(0, 183, 255);
leds[67] = CRGB(0, 183, 255);
leds[72] = CRGB(0, 183, 255);
leds[73] = CRGB(0, 183, 255);
leds[75] = CRGB(0, 183, 255);
leds[77] = CRGB(0, 183, 255);
leds[78] = CRGB(0, 183, 255);
leds[79] = CRGB(0, 183, 255);
leds[80] = CRGB(0, 183, 255);
leds[81] = CRGB(0, 183, 255);
leds[83] = CRGB(0, 183, 255);
leds[84] = CRGB(0, 183, 255);
leds[85] = CRGB(0, 183, 255);
leds[86] = CRGB(0, 183, 255);
leds[87] = CRGB(0, 183, 255);
FastLED.show();
delay(3000);
FastLED.clear();

break;
case '5':
for(int i=0;i<4;i++)
{
static uint8_t hue;
for(int i = 0; i < NUM_LEDS/2; i++) {
// fade everything out
leds.fadeToBlackBy(40);

// let's set an led value


leds[i] = CHSV(hue++,255,255);

// now, let's first 20 leds to the top 20 leds,


leds(NUM_LEDS/2,NUM_LEDS-1) = leds(NUM_LEDS/2 - 1 ,0);
FastLED.delay(33);
}
}
break;

case '6':
{
for(int i=0;i<3;i++)
{
static uint8_t hue = 0;
Serial.print("x");
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(hue++, 255, 255);
FastLED.show();
fadeall();
delay(10);
}
Serial.print("x");
for(int i = (NUM_LEDS)-1; i >= 0; i--) {
leds[i] = CHSV(hue++, 255, 255);
FastLED.show();
fadeall();
delay(10);
...

This file has been truncated, please download it to see its full contents.
85) Arduino Automated Aeroponic System Wifi

COMPONENTS AND SUPPLIES


Arduino Mega 2560 & Genuino
Mega 2560 × 1

NodeMCU ESP8266 Breakout


Board
× 1

TaydaElectronics MINI RELAY


SPDT 5 PINS 12VDC 10A 120V
CONTACT × 3

Adafruit Waterproof DS18B20


Digital temperature sensor
× 1

DFRobot Gravity: Analog LM35


Temperature Sensor For Arduino
× 1

SparkFun Dual H-Bridge motor


drivers L298
× 1

DHT22 Temperature Sensor

× 1

Male/Female Jumper Wires


× 3

DFRobot I2C 16x2 Arduino LCD


Display Module
× 1

Module peltier 12706


× 1

Module RTC 1302


× 1

Hw 125 MicroSD Reader


× 1

Peristaltic pump 12v 7w 11ml/min


× 2

Water pump 12v brushless


× 3

Plastic box 30X20X12cm


× 3

Heatsink from PC watercooling


× 1

8mm pvc pipe 5meter


× 1

1mm silicon pipe 5meter


× 1
NECESSARY TOOLS AND MACHINES
Hot glue gun (generic)

Soldering iron (generic)

Multitool, Screwdriver

Drill / Driver, Cordless

Manual saw

ABOUT THIS PROJECT

Introduction
Hi, I'm a chemical engineering student. Until I started this project I had
no idea how to code. I started with blink... two months ago... thanks to
the lockdown. I can't guarantee that my code is written according to the
rules. But I've tested it for hours, days, it works.
I challenge myself in many ways, in this project, I did it for myself; it's
not a school project or anything else. I started from scratch. I used a lot
of lines of code from other sources, but in the end, I started writing my
own. I'm not in a good position to teach someone because I'm a
beginner. But I think that since I've read tons of projects and trained for
over 450 hours reading, coding and failing tons of times, maybe this
one can help people. Besides, knowledge dies when it's not shared.

Main view inside the greenhouse


The roots parts with the nutrient pipe in the middle
Main solution with sensors, filter, coldsink peltier, watering pump, and
drain pump for cleaning

The electrical case with acrylic cover

The Black Sheep mascot


What the system can do?
The system i've made currently can record, set and monitor through
WebBrowser these differents parameters:
Water temperature
Air temperature (inside the greenhouse)
Air temperature inside the electronical box
Humidity level
TDS (Nutrient )
Time Trigger for Light
Time Trigger for Watering On/Off Cycle
All the datas can be stored in SDcard
Water level with AutoRefill (Sensor +pump+relay)*
Humidity with mistmaker and fan (Mistmaker + fan+relay)*
Legend for* [Will be added soon]
WebServer Video Demostration
https://streamable.com/w97i19
This is the link of WebServer access by Iphone8 on 4g connexion.
Description of the content of the video:
First I check the error page if log are false (that was made for 20 April )
Then I push a button to see the confirmation message
After that I check no blank formular and ranged value and submit to
see response of the arduino the value come from it after refresh
The home page contain some casual widget
It's fully optimised for SmartPhone Browser
You can Monitor data collected by sensor
You can switch on/off light and pump manualy
You can set time trigger for light and watering
You can set Water temperature and TDS value
SCHEMATICS
CODE
int getMedianNum(int bArray[], int iFilterLen)
{
int bTab[iFilterLen];
for (byte i = 0; i < iFilterLen; i++)
bTab[i] = bArray[i];
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++)
{
for (i = 0; i < iFilterLen - j - 1; i++)
{
if (bTab[i] > bTab[i + 1])
{
bTemp = bTab[i];
bTab[i] = bTab[i + 1];
bTab[i + 1] = bTemp;
}
}
}
if ((iFilterLen & 1) > 0)
bTemp = bTab[(iFilterLen - 1) / 2];
else
bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
return bTemp;
}

byte Heart[8] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};

//=========================================debut Muoton"Black Sheep"


Alexandros Pantelidis Avril 2020=================================
byte tete1[8] =
{
0b00011,
0b00100,
0b01010,
0b10000,
0b11111,
0b00011,
0b00011,
0b00010
};

byte tete2[8] =
{
0b11000,
0b11100,
0b10001,
0b11110,
0b10001,
0b11000,
0b11111,
0b10001
};

byte tete3[8] =
{
0b00000,
0b00000,
0b10011,
0b01110,
0b10001,
0b00100,
0b10001,
0b01110
};

byte tete4[8] =
{
0b00000,
0b00000,
0b00000,
0b10000,
0b01000,
0b01000,
0b11100,
0b10110
};

byte bas1[8] =
{
0b00010,
0b00010,
0b00011,
0b00001,
0b00001,
0b00000,
0b00000,
0b00000
};
byte bas2[8] =
{
0b01011,
0b01100,
0b00111,
0b01000,
0b11111,
0b01001,
0b01001,
0b01001
};

byte bas3[8] =
{
0b00011,
0b11001,
0b00000,
0b10100,
0b11111,
0b00010,
0b00010,
0b00010
};

byte bas4[8] =
{
0b10001,
0b01001,
0b00101,
0b10011,
0b11110,
0b00100,
0b00100,
0b00100
};
//=========================================Fin
mouton=================================
//=========================================Librarie
utilisées=========================
#include <EEPROM.h>
#include <DHT.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <SD.h>
#include <LiquidCrystal_I2C.h>
#include <virtuabotixRTC.h> //Library used
#include <ResponsiveAnalogRead.h>
//=========================================Pin
definie=================================
#define RELAY1 24
#define POMPES 22
#define LAMPES 26
#define moteurA_1 38
#define moteurA_2 40
#define moteurB_1 36
#define moteurB_2 34
#define DS1302_GND_PIN 33
#define DS1302_VCC_PIN 31
#define Tbox A2
#define DHTPIN 32 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
#define TdsSensorPin A8
#define VREF 5.0 // analog reference voltage(Volt) of the ADC
#define SCOUNT 3 // sum of sample point
#define ONE_WIRE_BUS 7
//=========================================Constantes
utiilisées============================
unsigned long currentMillis1 = 0;
unsigned long currentMillis4 = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis = 0;
unsigned long previousMillis3 = 0;
const long interval = 10000;
unsigned long periodtds = 3600000; // 1h
const long nettoyage = 10000;
const int chipSelect = 49;
unsigned long startMillis1;
unsigned long startMillis;
String message = "";
bool messageReady = false;
String message1 = "";
bool messageReady1 = false;

int analogBuffer1[SCOUNT]; // store the analog value in the array, read from ADC
int analogBufferTemp1[SCOUNT];
int analogBufferIndex1 = 0, copyIndex1 = 0;

int analogBuffer[SCOUNT];
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0, copyIndex = 0;
float averageVoltage = 0 , tdsValue = 0;

int analogBuffer2[SCOUNT];
int analogBufferTemp2[SCOUNT];
int analogBufferIndex2 = 0, copyIndex2 = 0;
float averageVoltage2 = 0;

int val;
int addr = 0;

const byte numChars = 64;


char receivedChars[numChars];
char tempChars[numChars];
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;
boolean newData = false;

int ledstate;
int pompestate;

int int1;
int int2;
int int3;
int int4;
int int5;
int int6;
int int7;

int minteau ;
int maxteau ;
int timearro;

float temperature;
float humi;
float temp;
float tbox;
int tdsval;

int OnHour;
int OnMin; //set hour and minutes for timer

int OffHour;
int OffMin;

int valeur_brute;
bool freshtds = false;
bool cleanup = false;
bool perioff = true;
//=========================================Fonction
declaré============================

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line
display
DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
ResponsiveAnalogRead analog(Tbox, true);
virtuabotixRTC myRTC(35, 37, 39); //If you change the wiring change the pins here also
//=========================================Fonction demmarage
============================
void LedState() {

val = EEPROM.read(addr);
if (val == 1)
{
digitalWrite(LAMPES, HIGH);

}
if (val == 2)
{
digitalWrite(LAMPES, LOW);
}
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);

Serial.println(maxteau);
Serial.println(minteau);
Serial.println(OnHour);
Serial.println(OnMin);
Serial.println(OffHour);
Serial.println(OffMin);
Serial.println(tdsval);
Serial.println(timearro);

//=========================================Executé au
demmarage============================
void setup() {
Serial.begin(9600);
delay(1);
Serial1.begin(115200);
delay(1);
Serial.print("Initializing SD card...");
delay(1);

if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
while (1);
}
Serial.println("card initialized.");
dht.begin();
sensors.begin();
pinMode(TdsSensorPin, INPUT);
pinMode(RELAY1, OUTPUT);
pinMode(POMPES, OUTPUT);
pinMode(LAMPES, OUTPUT);
pinMode(Tbox, INPUT);
pinMode(moteurA_1, OUTPUT);
pinMode(moteurB_1, OUTPUT);
pinMode(moteurA_2, OUTPUT);
pinMode(moteurB_2, OUTPUT);
digitalWrite(POMPES, HIGH);
digitalWrite(moteurA_1, LOW);
digitalWrite(moteurA_2, LOW);
digitalWrite(moteurB_1, LOW);
digitalWrite(moteurB_2, LOW);
digitalWrite(DS1302_GND_PIN, LOW);
pinMode(DS1302_GND_PIN, OUTPUT);
digitalWrite(DS1302_VCC_PIN, HIGH);
pinMode(DS1302_VCC_PIN, OUTPUT);

LedState();
startMillis1 = millis();
startMillis = millis();
lcd.init();
lcd.createChar(0, Heart);
lcd.createChar(1, tete1);
lcd.createChar(2, tete2);
lcd.createChar(3, tete3);
lcd.createChar(4, tete4);
lcd.createChar(5, bas1);
lcd.createChar(6, bas2);
lcd.createChar(7, bas3);
lcd.createChar(8, bas4);
lcd.backlight();
lcd.setCursor(0, 0);

lcd.print("Alex's Hydro Box");


lcd.setCursor(3, 1);
lcd.print("Bienvenue ^^");
delay(5000);
lcd.clear();
//myRTC.setDS1302Time(0, 8, 19, 2, 7, 4, 2020);

//=========================================Set cycle arrosage


/on/off============================

void setpompe() {
timearro = EEPROM.read(9);

currentMillis1 = millis(); //get the current "time" (actually the number of milliseconds
since the program started)
if (currentMillis1 - startMillis >= (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 endMarker = '>';
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 <= tdsval && tdsValue != 0 && freshtds == false && pompestate == 1 &&
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 <= minteau && temperature != -127 && temperature != 0)
{
digitalWrite(RELAY1, LOW);

}
else {
;
}
}

void average() {
static unsigned long analogSampleTimepoint = millis();
if (millis() - analogSampleTimepoint > 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.print(ledstate);
Serial1.print(",");
Serial1.print(pompestate);
Serial1.print(",");
Serial1.print(tdsValue, 0);
Serial1.print(",");
Serial1.print(temp, 2);
Serial1.print(",");
Serial1.print(temperature, 2);
Serial1.print(",");
Serial1.print(humi, 2);
Serial1.print(",");
Serial1.print(tbox, 2);
Serial1.print(",");
Serial1.print(tdsval);
Serial1.print(",");
Serial1.print(OnHour);
Serial1.print(",");
Serial1.print(OnMin);
Serial1.print(",");
Serial1.print(OffHour);
Serial1.print(",");
Serial1.print(OffMin);
Serial1.print(",");
Serial1.print(maxteau);
Serial1.print(",");
Serial1.print(minteau);
Serial1.print(",");
Serial1.print(timearro);
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

Arduino Nano R3

× 1
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 <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <SevSeg.h>
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); //memorizza ora
String d = c.substring (0,4); //memorizza cifra a 4 digit
d.toCharArray(text[2],5); //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

Male/Female Jumper Wires

× 1

I2C Serial Adapter


× 1
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 address<16. Here we print the
address in Hexadecimal. The printing instruction is
"Serial.print(address, HEX)". And count the Device. The complete I2C
Scanner code is given below
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int Devices;
Serial.println("Scanning...");
Devices = 0;
for(address = 1; address < 127; address++ )
{

Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
Devices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (Devices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000);
}
Upload the I2C Scanner Code to Arduino Uno.
Step- 2
If you have a I2C LCD please skip this step. But if you have a 16x2
LCD and a I2C Module see the step to connect this module to LCD.
Connection
First solder the I2C Module. There is no label on the I2C Module for
connecting to 16x2 LCD. So solder it with the help of the image given
below

I2C Module on 16x2 LCD


After soldering connect the I2C Module to Arduino Uno.
Arduino Uno I2C module
Analog Pin 4 - SDA
Analog pin 5 - SCL
5V - Vcc
GND - GND
Connect the Arduino to computer.
Next open Serial monitor from the icon on top right corner of Arduino
IDE. And set the baud rate as 9600. Please ensure the correct port.
Then you can see the address of LCD in serial monitor like shown
below

Finally we find the address of the I2C LCD. That is 0x27


Step - 3
Next I am going to display a text on our I2C LCD.
Before that need to add a library to Arduino IDE. Go to the link and
download the library Arduino-LiquidCrystal-I2C-library. Then open
Arduino IDE and go to Sketch>Include Library> Add.ZIP Library.
Next select the downloaded ZIP file and click open.
Step - 4
Next create a sketch. First I include the header "Wire.h". This library
help to communicate with I2C device. Then include
"LiquidCrystal_I2C.h" for better communication with display.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
Step - 5
Next set the address, number of column and number of rows using the
function "LiquidCrystal_I2C lcd(). The address is 0x27 (discovered
using the I2C Scanner Code). Number of columns is 16 and number of
rows is 2. After this, we can call the display using "lcd". You can also
use multiple I2C LCDs with Arduino Uno. But set different addresses
and variable for each display.
LiquidCrystal_I2C lcd(0x27, 16, 2);
Step - 6
Next code the setup part. First initialize the display using the function
"lcd.begin()". If you have another display initialize them.
lcd.begin();
Step - 7
Next turn on the backlight using the function "lcd.backlight()".
lcd.backlight();
Step - 8
Next clear the lcd using the instruction "lcd.clear()". Then set the
cursor to the position (4, 0).
lcd.clear();
lcd.setCursor(4,0);
Step - 9
Now the LCD is ready to print. The cursor is at 4th column(count from
0), and 0th row(count from 0). Then print the Message "Hackster" by
the function "lcd.print()".
lcd.print("Hackster");
Then leave the loop part as empty.
The programming is completed. Upload the sketch to Arduino and see
the message on LCD. The complete code is given in the Code section
of this article.

SCHEMATICS
CODE

//sketch created by Akshay Joseph


#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{

lcd.begin();

lcd.backlight();
lcd.clear();
lcd.setCursor(4,0);
lcd.print("Hackster");
}

void loop()
{
}
88) Lego Gun Shooter with and Arduino

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO


This is the board I used for this
× 1
project. However, an Arduino
Uno would work as well.
SG90 Micro-servo motor
These are the motors needed for × 4
the project.

Jumper wires (generic)

× 1

Lego Star Wars Shootable Cannon


× 4

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE
A program that runs Arduino Code on Mac,
Windows, and Linux Devices.

ABOUT THIS PROJECT

This project is about getting Lego Cannons to shoot automatically. I


like playing with legoes, and I like using Arduinos, so I decided to do
this project in my free time. The Servos spin around, hitting the lever
and shooting the cannon. A great first, second or third project for
beginners!
This is a step by step guide on how to make it.
Step 1) The Basics
Start with VIN going to the positively charged row and GRND going to
the negatively charged row. It'll look like this -
Step 2) Hooking up Servo #1
The Servo has three wires - the orange/yellow (signal) one will take up
a slot in the DIGITAL (PWM~), the red one (Power) will go to VIN
(which is any pin in the positive row), and the black/brown wire
(GRND) will go to the negatively charged row connected to the GRND
pin on the Uno. The Digital pin that I used for my first servo is 7. Here
is how the schematic looks like when the first servo is hooked in -
Step 3) Wiring up the rest of the Servos
Once you get the hang of it with the servos, the rest should be a breeze.
One thing to note, however - you have to keep consistent with the
Digital Pins you attached with your servo in the code.
For example, the code (which can be found at the bottom of the page),
states-
countServo2.attach(8);
Therefore, the second Servo must be connected to the digital pin 8.
In the same way, the third Servo must be attached to the digital pin 6,
and the fourth should be attached to the ninth digital pin.
However, these can be changed so that they are in any order you want
them to be. Just make sure you are changing both hardware and
software for consistency, otherwise, the code will not work.
To run with the code provided at the bottom, this is how the schematic
should look like-

Note - It may look complicated, but as I said before, it is much easier


than it looks once you get the hang of it
Congratulations! You have officially completed the hardware portion of
this project.
Now, copy and paste the code at the bottom of the page onto an
Arduino sketch, and upload it. Make sure you have the Servo library
before uploading the code, otherwise it will not work! If you have any
other issues, you can comment in the comments section and I will
respond ASAP. If it works, the congratulations.
The last step requires the lego cannons and some old-fashioned regular
tape. The lego cannon looks like this -
The
Lego cannon
Run the code. See which way the servo turns. Tape the servo onto the
lego cannon so that its trajectory sets it on a collision course with the
lever on top of the cannon in the picture above.
SCHEMATICS
CODE
#include <Servo.h>

float duration, distance;

Servo countServo;
Servo countServo2;
Servo countServo3;
Servo countServo4;

void setup() {

Serial.begin(9600);

countServo.attach(7);
countServo.write(180);
delay(700);
countServo.write(0);
delay(700);
countServo.write(180);
countServo2.attach(8);
countServo2.write(180);
delay(700);
countServo2.write(0);
delay(700);
countServo2.write(180);
countServo3.attach(6);
countServo3.write(180);
delay(700);
countServo3.write(0);
delay(700);
countServo3.write(180);
countServo4.attach(9);
countServo4.write(180);
delay(700);
countServo4.write(0);
delay(700);
countServo4.write(180);
}

void loop() {
{
countdownServo();

}
delay(100);
{
countdownServo2();
}
delay(100);
{
countdownServo3();
}
delay(100);
{
countdownServo4();
}
}

void countdownServo() {
int halfseconds = 5;

for (int i = halfseconds; i >= 0; i--) {

countServo.write((int)(i * 4.5));
delay(500);
}

countServo.write(180);
delay(700);
}

void countdownServo2() {
int halfseconds = 5;

for (int i = halfseconds; i >= 0; i--) {

countServo2.write((int)(i * 4.5));
delay(500);
}

countServo2.write(180);
delay(700);
}
void countdownServo3() {
int halfseconds = 5;

for (int i = halfseconds; i >= 0; i--) {

countServo3.write((int)(i * 4.5));
delay(500);
}
countServo3.write(180);
delay(700);

void countdownServo4() {
int halfseconds = 5;

for (int i = halfseconds; i >= 0; i--) {

countServo4.write((int)(i * 4.5));
delay(500);
}

countServo4.write(180);
delay(700);
}
89) DIY Arduino Height Measuring Machine

COMPONENTS AND SUPPLIES


Arduino Nano R3
× 1

Ultrasonic Sensor - HC-SR04


(Generic)
× 1

Alphanumeric LCD, 16 x 2

× 1

Trimmer Potentiometer, 10 kohm

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

ABOUT THIS PROJECT

When I noticed that my kids were measuring their height every day, I
got the idea to make such a device. To find out your height, all you
have to do is stand under the device and activate a sound that indicates
that your height has been measured.
It is very easy to build and consist only a few components:
-Arduino Nano
-HC SR04 ultrasonic sensor
-LCD display
-Buzzer
-Battery
Now let's explain how it works:
First we need to install the device with the help of double-sided
adhesive at a certain height, which is previously defined in the code,
and is marked with the letter H on the picture
When someone stands under the device, the sensor measures the
distance D. Next the code calculates the distance H-D which actually
represents the height of the person under the device H1 and displays
this value on the LCD. Library "LcdBarGraph" helps draw horizontal
bargraph, where the length of the bar is proportional to the values
provided. When there is no one under the device, the calculated value
is zero because in this case H = D and H-D is zero. The device is
mounted in a suitable box with the LCD on the front and the ultrasonic
sensor on the bottom.
.

SCHEMATICS
CODE

// includes the LiquidCrystal Library


#include <LiquidCrystal.h>

// includes the LcdBarGraph Library


#include <LcdBarGraph.h>

// Maximum distance we want to ping for (in centimeters).


#define max_distance 200

// Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

LcdBarGraph lbg(&lcd, 16, 0, 1); // Creates an LCD Bargraph object.

const int trigPin = 9;


const int echoPin = 10;
long duration;
int distance;
int distance1;
int speakerPin = 8;
void setup()
{
lcd.begin(16,2); // Initializes the interface to the LCD screen

pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}

void loop()
{
// Write a pulse to the HC-SR04 Trigger Pin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// Measure the response from the HC-SR04 Echo Pin


duration = pulseIn(echoPin, HIGH);

// Determine distance from duration


// Use 343 metres per second as speed of sound
distance= duration*0.034/2;
distance1= 180 - distance ;
// Prints "Distance: <value>" on the first line of the LCD

if (distance1 > 100) {


tone (speakerPin, 1000);

} else {
noTone (speakerPin);

}
lcd.setCursor(0,0);
lcd.print("HEIGHT: ");
lcd.print(distance1);
lcd.print(" cm ");

// Draws bargraph on the second line of the LCD


lcd.setCursor(0,1);
lbg.drawValue(distance1, max_distance);
delay(500);
}
90) Arduino Retro LED Bubble Display

COMPONENTS AND SUPPLIES

NSA1166
× 1

Resistor 220 ohm

× 6
Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Male Header 40 Position 1 Row


(0.1")
× 1

Arduino MKR WiFi 1010

× 1

ABOUT THIS PROJECT

The display is a common cathode type seven-segment, six-digit array.


It actually works a lot like the seven-segment LED displays which have
libraries and tutorials available which was a good starting point.
I got it working with some minor modification to the SparkFun SevSeg
library that already supports four-digit displays. I just added an extra
two digits. The result looked pretty cool:

However, unlike the modern Serial displays it does not have a built-in
controller or a SPI interface - this means that Arduino pins need to be
connected to each segment (7) and a select pin for each digit (6). The
LED display is illuminated by the Arduino continually strobing across
each digit in order, and setting the right segments for that digit for just
a fraction of a second. If the Arduino sketch stops doing this, the
display will go blank or flicker.
Keeping the lights on
Of course, it's being driven by an Arduino MKR WiFi 1010 so there is
some Internet connected fun that could be had.
But fetching some data from the Internet takes time, and waiting for the
operation to complete means the display would go blank. A way to
solve this is to use timer-based interrupts in order to continually update
the LED display in the background.
SCHEMATICS
CODE

#include "SevSegPlus.h" // https://github.com/8bitkick/SevSegPlus

SevSegPlus ledDisplay;

void setup()
{
ledDisplay.begin();
}

void loop()
{
ledDisplay.print(" Hi ");
delay(1000);

ledDisplay.print("There ");
delay(1000);
}
91) Arduino Battery Capacity Tester
COMPONENTS AND SUPPLIES

SparkFun Arduino Pro Mini 328 -


5V/16MHz
× 1
Can be gotten just about anywhere
online.
20x4 LCD white on blue, with
backlite
Original project used Nokia 5110 × 1
LCD. I don't have any on hand. I
do have several of these....
Power MOSFET N-Channel
Close enough, I used what I had
× 1
on hand, an AO D3N50 HEXFET.

I2C/twi/spi interface module for


20x4 LCD
× 1
Saves pins, and libraries work
quite well with these.
SparkFun Pushbutton switch 12mm

× 1

Female Header 8 Position 1 Row


(0.1")
Close. I bought several 20x1 × 1
sticks from eBay, and cut what I
needed from them.
terminal block two position
× 2
generic screw terminal block
8 ohm 2w resistor
× 1
Needs to be at least 2W.
Resistor 10k ohm

× 2

Speaker: 0.25W, 8 ohms

× 1

prototyping pc board
× 1

wire
× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

solder

diagonal cutters
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

I have, for a long while, avoided the use of Li-Ion type batteries, owing
to the cost and special charging profiles needed. Now that the
technology is more mature, I am venturing into their use.
Since my supply of cells will be primarily used stock from various
recycle streams, I needed to come up with the tools to test each cell.
With that in mind, here's my derivative of this tester.
What I did
The main changes I did are the 20x4 LCD rather than buying a Nokia
5110 that the original author used. I also used the I2C/TWI/SPI
interface board for the LCD screen.
Note that the SCL and SDA pins are NOT broken out on the pro mini,
they are on the A5 and A4 pins, as noted in the sketch.
Any MOSFET capable of 2.5A constant current or better can be used,
best to use one with the lowest Rds on that you can. The one used here
actually has a fairly high Rds on of 2.4 Ohm typical. This may actually
skew the mAh results. This means that my cells may have a slight bit
higher storage capacity than indicated. I had these on hand, left over
from a previous project. This particular HEXFET/MOSFET is SMD,
but the gate and source pins line up with the .1" spacing on a
protoboard. Easy to solder, and even gives a few vias under the drain
tab to add a heat sink under the board if needed.
Bad pic, and bad solder job... got it twisted a bit. The resistor is a pull-
down on the gate.
The odd headers for the speaker and LCD are recycled from an old
printer I tore apart. I used a 6 position female header section for the
load resistor, so I can change the load if I need to. I just have to
remember to change the code to match whatever I use. 3 position on
each end are paralleled, so I can match resistance to whatever load mA
I want to use according to the type of cell I'm testing.
Lower right screw block is for 5V power in, upper left block is test cell
connection.
The rat's nest of point to point wiring to make the connections. Maybe I
should have used several different colors to make it easier to trace
should I have a problem later on.
The I2C/TWI/SPI interface board. Cheap on eBay, or Aliexpress, as
long as you don't mind waiting 4-6 weeks for delivery. Can be bought
anywhere worldwide online.
Second view of the LCD, showing the changes from the title image.
Still to do is a case for it, might even need to change the screw blocks
out for something else.
SCHEMATICS
CODE
/*
* Li-Ion capacity tester.
* set up:
* 8 Ohm discharge load
* ~190mA discharge rate.
* I2C LCD.
* MOSFET for discharge control.
* SCl pin = A5
* SDA pin = A4
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

//LCD set-up
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20 chars and 4 line
lcd

// definitions

#define STATE_WAITING 0
#define STATE_MEASURING 1
#define STATE_MEASURING_ENDED 2
#define BAT_LI 0
#define BAT_NI 1
#define BAT_UNREC 2
#define BAT_LI_DISCHARGED 3

//variables

float vtgBatLoaded; //shows the drop in cell V under load


float vtgBatUnloaded; //cell V for no load
float vtgLoad;
float vtgDropOnLoad;
float vtgDropRin;
float rLoad=8; //resistanse of the load in Ohms
float rIn; //calculated cell internal resistance
float batCurrent;
float mAh; //running total cell capacity
uint8_t FET_Base=7; //otherwise known as the Gate.
uint8_t button = 6;
uint8_t speaker= 5;
uint8_t state=STATE_WAITING;
float LiChargedVtg=4.35;
float LiCutoffVtg=2.9;
float NiChargedVtg=1.45;
float NiCutoffVtg=1.1;
float cutoff;
uint8_t BatteryType;
boolean DischargeAllowed=false;
String BatTypeString;

void setup()
{
pinMode(FET_Base,OUTPUT);
pinMode(button,INPUT); //can be changed in the circuit to active low,
// will need to turn on the internal pull-up
pinMode(speaker,OUTPUT);
digitalWrite(FET_Base,LOW);
noTone(speaker);
lcd.init();
lcd.backlight();
}

void loop()
{
if (state==STATE_MEASURING)
{
vtgBatUnloaded=analogRead(0)*5.0/1024.0; //get the voltage of UNLOADED battery

if (vtgBatUnloaded<cutoff)
{
state=STATE_MEASURING_ENDED;
DischargeAllowed=false;
for (uint8_t i=0;i<4;++i)
{tone(speaker,2000,500); delay(500);noTone(5);delay(300);}
}
digitalWrite(FET_Base,HIGH); //turn the MOSFET on
delay(1000);
vtgBatLoaded=analogRead(0)*5.0/1024.0; //get the voltage of LOADED battery
vtgLoad=analogRead(1)*5.0/1024.0;
digitalWrite(FET_Base,LOW);//turn the MOSFET off
vtgDropOnLoad=vtgBatLoaded-vtgLoad;
if(vtgDropOnLoad>0) batCurrent=vtgDropOnLoad/rLoad;
else batCurrent=0;
vtgDropRin=vtgBatUnloaded-vtgBatLoaded;
if(batCurrent>0) rIn=vtgDropRin/batCurrent;
else rIn=0;
mAh+=batCurrent/3.6; //*1000.0/3600.0;
lcd.clear();
lcdState();
lcd.setCursor(0,0);
lcd.print(" Bat Load I ");
lcd.setCursor(0,1);
lcd.print(vtgBatUnloaded); lcd.print("V ");lcd.print(vtgBatLoaded); lcd.print("V
");lcd.print(batCurrent); lcd.print("A");
lcd.setCursor(0,2);
lcd.print("Rin= "); lcd.print(rIn); lcd.setCursor(11,2); lcd.print(" Ohm");
lcd.setCursor(0,3);
lcd.print("Cap= "); lcd.print(mAh); lcd.print(" mA/h");
delay(500);
}
else if (state==STATE_WAITING)
{
digitalWrite(FET_Base,LOW);//turn the MOSFET off
vtgBatUnloaded=analogRead(0)*5.0/1024.0; //get the voltage of UNLOADED battery
DefBatteryType();
lcd.clear();
lcdState();
lcd.setCursor(0,0);
lcd.print("Bat= "); lcd.print(vtgBatUnloaded); lcd.print(" V");
lcd.setCursor(0,1);
lcd.print(BatTypeString);
lcd.setCursor(0,2);
lcd.print("Test ");
if (DischargeAllowed) lcd.print("allowed");
else lcd.print("denied");
CheckButtons();
delay(500);
}
else if (state==STATE_MEASURING_ENDED)
{
digitalWrite(FET_Base,LOW);//turn the MOSFET off
vtgBatUnloaded=analogRead(0)*5.0/1024.0; //get the voltage of UNLOADED battery
lcd.clear();
lcdState();
lcd.setCursor(0,0);
lcd.print("Bat= "); lcd.print(vtgBatUnloaded); lcd.print(" V");
lcd.setCursor(0,1);
lcd.print("Cap= ");lcd.print(mAh); lcd.print(" mA/h");
CheckButtons();
delay(500);
}
}

void CheckButtons(void) {

if (digitalRead(button)==HIGH){ // if changed to active low.....you know what to do!


switch (state){

case STATE_WAITING : DefBatteryType();


if (DischargeAllowed){ mAh=0; state=STATE_MEASURING;
tone(speaker,1000,500); delay(500);noTone(5);}
break;

case STATE_MEASURING : state=STATE_MEASURING_ENDED;


break;

case STATE_MEASURING_ENDED : state=STATE_WAITING;


break;
}
}
}

void lcdState(void){
String stateString;
lcd.setCursor(0,0);
if(state==STATE_WAITING) stateString="Waiting ";
if(state==STATE_MEASURING) stateString="Measuring ";
if(state==STATE_MEASURING_ENDED) stateString="Measuring done";
lcd.print(stateString);
}

void DefBatteryType(void){

if (vtgBatUnloaded>LiCutoffVtg&&vtgBatUnloaded<LiChargedVtg)
{BatteryType=BAT_LI; DischargeAllowed=true;BatTypeString="Li-ion
battery";cutoff=LiCutoffVtg;}
if (vtgBatUnloaded>NiCutoffVtg&&vtgBatUnloaded<NiChargedVtg)
{BatteryType=BAT_NI; DischargeAllowed=true;BatTypeString="Ni-MH battery
";cutoff=NiCutoffVtg;}
if (vtgBatUnloaded<LiCutoffVtg&&vtgBatUnloaded>NiChargedVtg)
{BatteryType=BAT_LI_DISCHARGED; DischargeAllowed=false;BatTypeString="Li-ion
battery";}
if (vtgBatUnloaded<NiCutoffVtg||vtgBatUnloaded>LiChargedVtg)
{BatteryType=BAT_UNREC; DischargeAllowed=false;BatTypeString="UNKNOWN bat
";}
}
92) Arduino RFID Controlled Light Switch
COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

ABOUT THIS PROJECT


This is a light swtich (but can be used for many other things) which can
be turned ON and OFF using dedicated 125 kHz RFID tags. In this
case, 10 different tags (users) can be used.
I have a underground room in the commune space in my bloc
(building) and to access this space I powered up a light system from
my apartment. The switch for the light is on the entrance in the cellar
and all my neighbors can access that space, and some of them put the
light ON "in purpose" only to increase my electricity bill :)). After a
while, I decided to do something to stop them doing this. Because the
building has a Electra access system using 125 kHz tags with unique
numbers I decided to use this tag because is attached to my keys all the
time.
I used for this project a Arduino Nano, RFID reader RDM 6300, one
5V relay, one old Nokia charger and other few parts.
The program is not very hard to understand and have explanations for
majority of the lines.
In OFF mode the white LED is ON (to be visible the box because is
installed in a dark zone). When a authorized tag is putted in front of
antenna the white LED goes OFF, green LED and relay goes ON and
the light is starting. If a unauthorized tag is used the white LED is
going OFF, red LED is coming ON for two seconds and after the white
LED is coming ON again, the relay remain OFF all the time.
To put OFF the light you need to put again close to antenna one
authorized tag, green LED become OFF, same the relay and the white
LED become ON. If one unauthorized tag is present, when the light is
ON, the green LED is going OFF and the red LED is going ON for two
seconds after the green LED is ON again, nothing happen with the
relay, the light remain on during this time.
After the light is ON you need to wait minimum two seconds before
you can put again the tag near antenna and get the light OFF. This cycle
can be repeated again and again and again...
SCHEMATICS

CODE
// define constants for pins

#include <SoftwareSerial.h>

int green_LED = 3;
int RELAY = 5;
int red_LED = 4;
int white_LED = 12;

SoftwareSerial ssrfid = SoftwareSerial(6,8);

// variables to keep state


int readVal = 0; // individual character read from serial
unsigned int readData[10]; // data read from serial
int counter = -1; // counter to keep position in the buffer
char tagId[11]; // final tag ID converted to a string
int ON_OFF = 2; //
char* authorizedTags[10]; // array to hold the list of authorized tags

void initAuthorizedTags() // fills the list of authorzied tags


{
// add your own tag IDs here
authorizedTags[0] = "1B00B2D95B"; //Tag 1
authorizedTags[1] = "0000000000"; //Tag 2
authorizedTags[2] = "0000000000"; //Tag 3
authorizedTags[3] = "0000000000"; //Tag 4
authorizedTags[4] = "0000000000"; //Tag 5
authorizedTags[5] = "0000000000"; //Tag 6
authorizedTags[6] = "0000000000"; //Tag 7
authorizedTags[7] = "0000000000"; //Tag 8
authorizedTags[8] = "0000000000"; //Tag 9
authorizedTags[9] = "0000000000"; //Tag 10
}

void setup()
{
Serial.begin(9600);
ssrfid.begin(9600);
ssrfid.listen();

pinMode(green_LED, OUTPUT);
pinMode(RELAY, OUTPUT);
pinMode(red_LED, OUTPUT);
pinMode(white_LED, OUTPUT);

digitalWrite(green_LED, LOW);
digitalWrite(RELAY, LOW);
digitalWrite(red_LED, LOW);
digitalWrite(white_LED, HIGH);

initAuthorizedTags();
}

int checkTag() // check if the tag ID we just read is any of the authorized tags
{
int i;
for (i = 0; i < 10; ++i)
{
if (strcmp(authorizedTags[i], tagId) == 0)
{
return 1;
}
}
return 0;
}

void parseTag() // convert the int values read from serial to ASCII chars
{
int i;
for (i = 0; i < 10; ++i)
{
tagId[i] = readData[i];
}
tagId[10] = 0;
}

void processTag() // once a whole tag is read, process it


{
parseTag(); // convert id to a string
printTag(); // print it
if (checkTag() == 1) // check if the tag is authorized
{
tagSuccess(); // if so, relay and green LED will be turned from OFF to ON or from ON
to OFF, depend the value of ON_OFF variable (odd or even)
}
else
{
tagFailed(); // otherwise, inform user of failure
}
}

void printTag()
{
Serial.print("Tag value: ");
Serial.println(tagId);
}

void tagSuccess() // perform an action when an authorized tag was read


{
Serial.println("Tag authorized.");
if ((ON_OFF % 2) == 0) // if ON_OFF is even number means the relay (light) and
the green LED is "off" and will go "on"
{
digitalWrite(green_LED, HIGH);
digitalWrite(RELAY, HIGH);
digitalWrite(white_LED, LOW);
digitalWrite(red_LED, LOW);
Serial.println("Light ON");
delay(2000);
}
else // if ON_OFF is odd number means the relay (light) and the green
LED is "on" and will go "off"
{
digitalWrite(green_LED, LOW);
digitalWrite(RELAY, LOW);
digitalWrite(white_LED, HIGH);
digitalWrite(red_LED, LOW);
Serial.println("Light OFF");
delay(2000);
}
ON_OFF ++; // increment ON_OFF for next cicle
}

void tagFailed() // inform the user that the tag is not authorized
{
Serial.println("Unauthorized access!");
digitalWrite(green_LED, LOW); // put the green LED low
digitalWrite(red_LED, HIGH); // put the red LED high, signal for unauthorized tag
delay(2000);
if ((ON_OFF % 2) != 0)
{
digitalWrite(green_LED, HIGH); // if tag fail and the light is on, green LED will be put
back high
}
}

void clearSerial() // this function clears the rest of data on the serial, to prevent
multiple scans
{
while (ssrfid.read() >= 0)
{
; // do nothing
}
}
void loop()
{
// turn red LED off
digitalWrite(red_LED, LOW);

if (ssrfid.available() > 0)
{
readVal = ssrfid.read(); // read the incoming byte:
if (readVal == 2) // a "2" signals the beginning of a tag
{
counter = 0; // start reading
}
else if (readVal == 3) // a "3" signals the end of a tag
{
processTag(); // process the tag we just read
clearSerial(); // clear serial to prevent multiple reads
counter = -1; // reset reading state
}
else if (counter >= 0) // if we are in the middle of reading a tag
{
readData[counter] = readVal; // save valuee
++counter; // increment counter
}
}

93) Presure Pad Interfacing with Arduino


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

SEN-09376 Pressure Pad


× 1
LED (generic)
× 3
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Pressure pads are designed to detect when pressure is applied to an


area, and they come in a variety of quality and accuracy. The simplest
pressure pads are often the equivalent of big switches. Inside a pressure
pad are two layers of foil separated by a layer of foam with holes in it.
When the foam is squashed, the metal contacts touch through the foam
and complete the circuit.
This tutorial serves as a quick primer on rressure pads and
demonstrates how to hook them up and use them with Arduino.

SCHEMATICS
CODE
const int FSR_PIN = A0; // Pin connected to FSR/resistor divider
const int LED_PIN1 = 7;
const int LED_PIN2 = 6;
const int LED_PIN3 = 4;
const float VCC = 4.98; // Measured voltage of Ardunio 5V line
const float R_DIV = 3230.0; // Measured resistance of 3.3k resistor

void setup()
{
Serial.begin(9600);
pinMode(FSR_PIN, INPUT);
pinMode(LED_PIN1, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
pinMode(LED_PIN3, OUTPUT);
}

void loop()
{
int fsrADC = analogRead(FSR_PIN);
// If the FSR has no pressure, the resistance will be
// near infinite. So the voltage should be near 0.
if (fsrADC != 0) // If the analog reading is non-zero
{
// Use ADC reading to calculate voltage:
float fsrV = fsrADC * VCC / 1023.0;
// Use voltage and static resistor value to
// calculate FSR resistance:
float fsrR = R_DIV * (VCC / fsrV - 1.0);
Serial.println("Resistance: " + String(fsrR) + " ohms");
// Guesstimate force based on slopes in figure 3 of
// FSR datasheet:
float force;
float fsrG = 1.0 / fsrR; // Calculate conductance
// Break parabolic curve down into two linear slopes:
if (fsrR <= 600)
force = (fsrG - 0.00075) / 0.00000032639;
else
force = fsrG / 0.000000642857;
Serial.println("Force: " + String(force) + " g");
Serial.println();
if(force<10)
{
digitalWrite(LED_PIN1,LOW);
digitalWrite(LED_PIN2,LOW);
digitalWrite(LED_PIN3,LOW);}
if(force>20)
{
digitalWrite(LED_PIN1,HIGH);
digitalWrite(LED_PIN2,LOW);
digitalWrite(LED_PIN3,LOW);

}
if(force>60)
{
digitalWrite(LED_PIN2,HIGH);
digitalWrite(LED_PIN1,LOW);
digitalWrite(LED_PIN3,LOW);
}
if(force>100)
{
digitalWrite(LED_PIN3,HIGH);
digitalWrite(LED_PIN2,LOW);
digitalWrite(LED_PIN1,LOW);
}

delay(500);

}
else
{
// No pressure detected
}
}

94) Arduino Automated Clothes Shoes Donation Machine


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

1Sheeld

× 1

Power Supply 12V/ 5A


× 1

Fan 12V
× 1

LED strips
× 1

Push Button
× 1

Android Smartphone
× 1

Relay Module 5V
× 1
APPS AND ONLINE SERVICES
Twitter

ABOUT THIS PROJECT

Q : Do you have clothes, shoes, books and ...etc that you no longer
want ?
A : Sure!
Q : What happens to these things? Stored for along time in your closet?
A : Yes :(
Now, pick these things you no longer want, and take them to the
nearest donation machine :)
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.
This machine is totally open source so you can build your own machine
at your district :) and i will be pleased if you shared your kindly
feedback to enhance the second version.You can download all the
needed files starting from the CAD files to the Arduino code, Enjoy :D
By the way, the machine was featured in a national TV show that
discuss out of the box solutions for enhancing our community.
Step 1: What you will need?
Materials:
1. MDF (8mm) Sheets
2. MDF (5mm) Sheets
3. Knotty pine wood
4. Stickers for the outer finish
5. Black Paint
6. Primer paint
7. Aluminum Bars
8. Hinge L3899-2B
Tools:>1. 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");<br>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 <OneSheeld.h>

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 <= 60 && distance2 <= 60) {
if (!isMessageSent)
{
// Send the SMS.

SMS.send("+201222326539 ", " ");

Terminal.println("Sending SMS done");

Terminal.println("Machine is filled");

// Set the flag.


isMessageSent = true;
}
}// if machine is filled

else
{
// Reset the flag
isMessageSent = false;

Terminal.println("Some one donated with something");

// Wait for 5 seconds while the user stand in front of the camera
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);

// read the state of the pushbutton value:


buttonState = digitalRead(buttonPin);

if (buttonState == HIGH) {

TextToSpeech.say("You have pressed the push button Please stand behind the red line");
OneSheeld.delay(6000);

Terminal.println("Bush Button is pressed");

for (int i = 1; i <= 3; i++) {


digitalWrite(ledPin, HIGH); // turn the LED on (HIGH is the voltage level)
OneSheeld.delay(1000); // wait for a second
digitalWrite(ledPin, LOW); // turn the LED off by making the voltage LOW
OneSheeld.delay(1000); // wait for a second
}//for

Camera.setFlash(ON);
// Take the picture.
Camera.rearCapture();
Terminal.println("Photo taken");

OneSheeld.delay(3000);
TextToSpeech.say("Yor photo has been taken");
OneSheeld.delay(7000);

// Post the picture on Twitter.


Twitter.tweetLastPicture(" ");
Terminal.println("Uploading");

TextToSpeech.say("Uploading your image");


OneSheeld.delay(4000);
TextToSpeech.say("Thank you");
// Wait for 5 seconds.
OneSheeld.delay(5000);

}// if button si pressed


else {
TextToSpeech.say("You didn't press the push button, Thank you sir");
OneSheeld.delay(6000);
}//Push button isn't pressed
}//Machine wasn't filled

}// if distance1 < 40 cm


}//void loop
95) Arduino Sodering Station

COMPONENTS AND SUPPLIES


Nano V3.0 ATmega328 For
Arduino × 1

IRF520 MOSFET Driver Module


for Arduino × 1

MAX6675 Module for Arduino


× 1

MAX7219 8-Digital Segment


Digital LED Display Tube For
Arduino × 1

Jumper wires (generic)

× 1

Cooling Fan 5V DC Brushless


0.10A 40mm x 40mm x 10mm 2pin
Connector Black × 1

Self Locking Electrical Cable


Connectors × 1

JST-XH Right angle Connectors


× 1

CASE200x120x75mm Plastic
Electronic Project Cover Enclosure × 1
Green Round Cap Push Button
Switch × 1

AC 16A/250V 20A/125V
Illuminated SPST Boat Rocker
Switch × 1

Soldering Station Iron Handle for


HAKKO 907 ESD × 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino Web Editor

EasyEDA

LibreCAD

ABOUT THIS PROJECT

Overview
Controls
On switching on power, our station in standby mode. It is mean that heater
do not connected and you can see iron handle current temperature on LED
display.
To start working need a long press on button 3 (Mode/ Standby). After this
station enters to last working mode stored in EEPROM memory.
There is two working mode named "CLASS 1" and "CLASS 2".
CLASS 1 is temperature control working mode. It is possible to set
desired temperature by two buttons 1 and 2 (UP and DOWN). Short press
change units for 1 and long press for 5. These values you can change in
sketch file:
const byte pinHeater = 2; //pin for irf520 module
const uint16_t minTemp = 50;//temperature minimum
const uint16_t maxTemp = 700;//temperature maximum
const uint16_t measInterval = 500; //measurement interval ms. over 500
const byte shortPressStep = 1; //temperature step on button's short press
const byte autoPressStep = 5; //temperature step on button's long press
On the right half of LED display you can see defined temperature and in
the left side real temperature of iron readied by thermocouple K-type.

CLASS 1 mode (temperature control)


CLASS 2. Power control mode. In this mode, you can set power level
from 0% to 100%. Controls is same in Class 1 - button 1 (up) and button 2
(down) long and short press. Right half display - desired power level and
left side - iron temperature.
Change working mode by short press on Button 3. Long press on button 3
to standby mode
Power control mode (CLASS 2)
If iron handle is unplugged or there is other problem and it is impossible to
read data from thermocouple, special symbol shown instead iron
temperature both in standby and in working mode
Unplugged handle detection in working mode
Unplugged handle in standby mode
Modules
Station have a module structure and almost not discreet components. Only
one descrete component is resistor for LED indicator of heating.
1. Power supply. I use power supply from old fax machine that have +5
and +24 volt out that i need.
2. Modules.
Arduino NANO. It placed on my own PCB with all needed connectors
an headers that i produce by laser transfer technology. However it is
possible to use breadboard for this target.
Assembled PCB
IRF520 mosfet module for heater control
IRF520 module
MAX6675 thermocouple K-type driver
max6675 module
MAX7219 8 digit module
That's all that you need!!!!!
In addition, you need a simple passive element such buttons, connectors,
wires and plugs.
Case
Assembling
Main Arduino module
LED display
Fully assembled
Finished

SCHEMATICS
CODE
//-- Libraries include
#include "LedControl.h" //max7219 7 segment display driver
#include "max6675.h" //thermocouple driver
#include "sav_button.h" //buttons library
#include "EEPROM.h" //Memory Storage

#include <SoftPWM.h> //Software PWM library


#include <SoftPWM_timer.h>

//-- Libraries definition


//------------------------------------------------
//-- MAX7219 LED segment display driver--------
const byte pinLedDIN = 13; //DATA-IN pin of MAX7219
const byte pinLedCLK = 11; //CLK pin of MAX7219
const byte pinLedCS = 12; //CS pin of MAX7219
LedControl led = LedControl(pinLedDIN, pinLedCLK, pinLedCS, 1);

//-- MAX6675 Thermocouple driver------------


const byte pinTcSO = 7;
const byte pinTcCS = 8;
const byte pinTcCLK = 9;
MAX6675 tc(pinTcCLK, pinTcCS, pinTcSO);

//-- PushButtons-----------------------------
const byte pinButtonUp = 4;
const byte pinButtonDown = 5;
const byte pinButtonOk = 6;
SButton Up (pinButtonUp, 50, 0, 800, 100);
SButton Down (pinButtonDown, 50, 0, 800, 100);
SButton Ok (pinButtonOk, 50, 1000, 4000, 250);

//-- Types definition


enum myUnits {
CELSIUS,
PERCENT
};

//-- Constatnts definition


const byte pinHeater = 2; //pin for irf520 module
const uint16_t minTemp = 50;//temperature minimum
const uint16_t maxTemp = 700;//temperature maximum
const uint16_t measInterval = 500; //measurement interval ms. Must be over 500
const byte shortPressStep = 1; //temperature change step on button's short press
const byte autoPressStep = 5; //temperature change step on button's long press

const int tempAddr = 0; // eeprom addresses


const byte powerAddr = 2;
const byte modeAddr = 3;

//-- Variables definition


uint16_t reqTemp = 60; //required temperature(celsius) from minTemp to maxTemp in
temperature mode
byte power = 50; //required power(percent) in power mode
byte mode = 0; //working mode (0 - temperature, 1 - power)
uint16_t temp; //Heater temperature
uint32_t measTime = millis();
boolean isChanged = true; // is any changes
boolean standBy = true; //standby mode on/off

byte logo[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x05, 0x3d,
0x1c, 0x10, 0x15, 0x1d, 0x00, 0x5b, 0x1d, 0x30, 0x3d, 0x4f, 0x05,
0x00, 0x5b, 0x0f, 0x77, 0x0f, 0x10, 0x1d, 0x15, 0x00, 0xed, 0x7e}; //Arduino Solder
station 1_0
byte class1[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x0e, 0x77, 0x5b,
0x5b, 0x00, 0x00, 0x30}; //CLASS 1
byte class2[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x0e, 0x77, 0x5b,
0x5b, 0x00, 0x00, 0x6d}; //CLASS 2
byte stby[] = {0x5b, 0x0f, 0x1f, 0x3b, 0x00, 0x00, 0x00, 0x00}; //STDBY

//-- My functions definition


void writeInfo(uint16_t num, byte group, myUnits units) { //Write info to led screen
(number, 4 digit group(0-right, 1-left, units (CELSIUS, PERCENT))
byte ones, tens, hundreds;

if (num==temp && temp==0 && units==CELSIUS) {


led.setRow (0, 0 + 4 * group, 0x00);
led.setRow (0, 1 + 4 * group, 0x78);
led.setRow (0, 2 + 4 * group, 0x4e);
led.setRow (0, 3 + 4 * group, 0x00);
}

else {

ones = num % 10;


tens = (num / 10) % 10;
hundreds = byte(num / 100);

if (units == CELSIUS) led.setRow (0, 0 + 4 * group, B01100011);


if (units == PERCENT)
{
if (power<34) led.setRow (0, 0 + 4 * group, B00001000);
if (33<power && power<67) led.setRow (0, 0 + 4 * group, B00001001);
if (power>66) led.setRow (0, 0 + 4 * group, B01001001);
//led.setRow (0, 0 + 4 * group, B01001001);

}
led.setDigit(0, 1 + 4 * group, ones, false);
if ( tens==0 && hundreds==0) led.setChar(0,2+4*group, ' ', false);
else led.setDigit(0, 2 + 4 * group, tens, false);
if (hundreds == 0) led.setChar(0, 3 + 4 * group, ' ', false);
else led.setDigit(0, 3 + 4 * group, hundreds, false);
}

}
// Read config from EEPROM
void readConf(){
uint16_t t;
byte p, m;
EEPROM.get(tempAddr, t);
if (minTemp<=t && t<=maxTemp) reqTemp = t;
EEPROM.get(powerAddr, p);
if (p>=0 && p<=100) power = p;
EEPROM.get(modeAddr, m);
if (m==0 || m==1) mode = m;
}

//save config to EEPROM


void saveConf(){
EEPROM.put(tempAddr, reqTemp);
EEPROM.put(powerAddr, power);
EEPROM.put(modeAddr, mode);
}
//set iron temperature
void setTemp(){
switch (mode){
case 0:
if (temp>=reqTemp){
SoftPWMSet(pinHeater, 0);
}
else {
SoftPWMSet(pinHeater, 255);
}
break;
case 1:
SoftPWMSet(pinHeater, map(power,0, 100, 0, 255));
break;
}
}
//show string on led dispaly
void ShowString(byte str[], byte sizeOfStr){
byte pos = 0;
for (byte i = 0; i<sizeOfStr-7; i++){
for(byte j=0; j<8; j++){
pos = i+j;
if (pos >= sizeOfStr) pos -= sizeOfStr;
led.setRow(0,7-j,str[pos]);
}
delay(80);
}
delay (800);
}

void unitsUp(byte vStep){


switch (mode){
case 0:
if ((reqTemp + vStep) <= maxTemp) {
reqTemp += vStep;
isChanged = true;
}
break;
case 1:
if ((power + vStep) <= 100) {
power += vStep;
isChanged = true;
}
break;
}

void unitsDown(byte vStep){

switch (mode){
case 0:
if ((reqTemp - vStep) >= minTemp) {
reqTemp -= vStep;
isChanged = true;
}
break;
case 1:
if ((int(power) - int(vStep)) >= 0) {
power -= vStep;
isChanged = true;
}
break;
}
}

void standByMode(){

SoftPWMSet(pinHeater,0);
led.setIntensity(0, 1);
for (byte i=0; i<5; i++) led.setRow(0,(7-i),stby[i]);
writeInfo(temp, 0, CELSIUS);

switch( Ok.Loop() ){
case SB_LONG_CLICK:
standBy = false;
led.setIntensity(0, 15);
if (mode == 0){
ShowString(class1, sizeof(class1));
isChanged = true;
}
else if (mode == 1){
ShowString(class2, sizeof(class2));
isChanged = true;
}
break;

}
}

void setup() {
led.shutdown(0, false);
led.setIntensity(0,15);
led.clearDisplay(0);

Up.begin();
Down.begin();
Ok.begin();

readConf();

//---- Soft PWM-----------------------------------


SoftPWMBegin();
SoftPWMSet(pinHeater, 0);
SoftPWMSetFadeTime(pinHeater, 4000, 0);
//------------------------------------------------
ShowString(logo, sizeof(logo));
standBy = true;

//Serial.begin(9600);
}

void loop() {
if ((millis()-measTime) > measInterval){
temp = tc.readCelsius();
measTime = millis();
// Serial.println(temp);
}

if (standBy) standByMode();
else{

switch( Up.Loop() ){
case SB_CLICK:
unitsUp(shortPressStep);
break;
/*case SB_LONG_CLICK:

break;*/
case SB_AUTO_CLICK:
unitsUp(autoPressStep);
break;
}
switch( Down.Loop() ){
case SB_CLICK:
unitsDown(shortPressStep);
break;
/*case SB_LONG_CLICK:

break;*/
case SB_AUTO_CLICK:
unitsDown(autoPressStep);
break;
}
switch( Ok.Loop() ){
case SB_CLICK:
if (mode == 0){
mode = 1;
ShowString(class2, sizeof(class2));
isChanged = true;
}
else if (mode == 1){
mode = 0;
ShowString(class1, sizeof(class1));
isChanged = true;
}
break;
case SB_LONG_CLICK:
standBy=true;
break;
/*case SB_AUTO_CLICK:
break;*/
}

if (isChanged) {
if (mode == 0) writeInfo(reqTemp, 0, CELSIUS);
if (mode == 1) writeInfo(power, 0, PERCENT);
saveConf();
isChanged = false;
}

setTemp();
writeInfo(temp, 1, CELSIUS);
}
}

96) Arduino LCD Backlight and Contrast Control


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1
Jumper wires (generic)

× 1

Rotary potentiometer (generic)

× 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

I am learning to program the Arduino and making myself some


tutorials so I can remember it more easily. I hope it will help you! If a
code translation is requested, I'll deliver it. In this project, I want to
show how you can control the backlight and contrast of a LCD 16x2
screen.
The only thing you have to do is send PWM Signals to V0 (contrast)
and A (backlight) on the LCD pins.

SCHEMATICS
CODE

#include <LiquidCrystal.h>

// Integer Bibliothek
int hintergrundLichtPIN = 8; // Hintergrundlicht PIN
int hintergrundLichtWert = 49; // Hintergrund Wert = Höher => 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

Arduino Ehernet Shield


× 1
DHT11 Temperature & Humidity
Sensor (4 pins) × 1

PIR Motion Sensor (generic)

× 1

LED (green)
× 1

Buzzer

× 1

SparkFun Breadboard Power


Supply 5V/3.3V
× 1
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 <DHT.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

// 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
× 1
using the Arduino 101 instead, but
it is incompatible with the
Sparkfun Color LCD Shield we
use.
Arduino Wifi Shield 101
We used an older version of this × 1
shield, not the 101.

TP-LINK M5250 3G Mobile Wi-Fi


× 1

AllThingsTalk IOTOPIA Rapid


Development kit
× 1
Grove Air Quality Sensor, Grove
Buzzer, Grove Base Shield
Sparkfun Color LCD Shield
× 1

Sparkfun Real Time Clock Module


× 1
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 <Wire.h>
#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 <SparkFunColorLCDShield.h>
#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 <avr/pgmspace.h>
#include <SPI.h>
#include <Temboo.h>
#include <Wire.h>
#include <WiFi.h>
#include <WiFiClient.h>

#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

Momentary Pushbutton Switch


× 1

Grove - Water Atomization v1.0


× 1

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.h>

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<nsum;i++)
{ // read 10 values for T & H
sensorValue2 += analogRead(A0);
sensorValue3 += analogRead(A1);
}
// average the value
int sensorValue2Avg=sensorValue2/nsum;
float RH= 0.1515*sensorValue2Avg-12.0;
int sensorValue3Avg=sensorValue3/nsum;
float Vt=(float) sensorValue3Avg*5.0/1023.0;
float R=(5.0-Vt)*10.0/Vt; // convert the value to relative humidity
float TinC=281.583*pow(1.0230,(1.0/R))*pow(R,-0.1227)-150.6614;
float TinF=TinC*(9.0/5.0)+32; // convert the temperature to fahrenheit
// print to serial monitor
Serial.print(RH,0);
Serial.println(" %RH");
Serial.print(TinC,1);
Serial.println(" deg C");
Serial.print(TinF,1);
Serial.println(" deg F");
Serial.print(R);
// print the value to lcd display
lcd.setCursor(0, 0);
lcd.print("%RH = ");
lcd.setCursor(6, 0);
lcd.print(R);
lcd.setCursor(0, 1);
lcd.print("T = ");
lcd.setCursor(5, 1);
lcd.print(TinC);
//
// if relatie humidity less than 40 % then turn on humidifire
// for 10sec.
if(R < 50){
digitalWrite(atomizationPin, HIGH);
delay(10000);
digitalWrite(atomizationPin, LOW);
sensorValue2=0;
sensorValue3=0;
delay(5000)
}
100) Arduino Advent Candle
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

White Plastic Tube


× 1

3 mm LED: Red

× 25
RTC DS3231
× 1

Yellow LED Flickering Candle


× 1

Rechargeable Li-ion Battery Pack 1200mAh


× 1

Speaker: 0.25W, 8 ohms

× 1

SparkFun Pushbutton switch 12mm

× 1

Slide Switch

× 1

Jumper wires (generic)

× 1

Round wood box


× 1
NECESSARY TOOLS AND MACHINES
Hot glue gun (generic)

Driller

Soldering iron (generic)


APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


I was always used to have an Advent Candle during December, but this
year we were not able to buy one in time. So I decided to build an
electronic one and control it with Arduino. Indeed it was a lot of work
and it was ready only by the 10th of December but, well, next year it
will still be working and I can program new effects!
I am controlling 25 LEDs with 10 GPIO pins, so I needed to build a
matrix of LEDs and make some multiplexing.
At the beginning, I was thinking to use a Raspberry Pi but I switched
soon to Arduino since such a board has been lying in a drawer for a
long time. The code is pretty naive at the moment. I hope to have a
better understanding of how to manage this kind of "parallel" stuff in
Arduino in the future: listening for a button press while controlling a
LED animation can be pretty tricky when you don't have threads. Do
you? I took inspiration
Candle on 14th of December
The hardest part was to put the LEDs from the inside... without
breaking the soldering
Lots of wires,,, a distinct colour for any of them in order to identify
them later
Fixing components into the box
Proper holes to access Arduino and battery recharge USB ports
Main ON/OFF switch
View of the lid from the bottom (not all cables have passed yet)
Candle stuck on the lid (with date decorations provided by my daughter
and her baby-sitter)
Silicon glue makes a nice "wax" effect
Now with the RTC module inside... we want to keep the date during
successive switching on and off and in the next days (also change
properly date at midnight)
Now just close the box and it's done (the buzzer has been later replaced
with a proper speaker)
Ready to plug!
Acknowledgements
This is actually my first "real" hardware project, involving more than
70 solder joints. I thought I would have never managed such a thing
and now I am pretty excited to have accomplished it. I need to thank
my uncle Stefano for inspiring, Edo for remembering I had an Arduino
and letting me discover Hackster.io, Daniele D.S. for providing the
main hardware component, my wife, Julia, for bearing with me while I
was playing with this stuff and my nephew Richard for encouragement
with his enthusiasm and helping with soldering.

SCHEMATICS
CODE

#include "Wire.h"
#include "pitches.h"
#define DS3231_I2C_ADDRESS 0x68

const int LOOPS = 7; // number of loops


const int BUTTON = 13; // pin number of button
const int SPEAKER = 14; // pin number of speaker

int cathods[] = {2,4,7,8,12}; // pins of cathodes


int anodes[] = {3,5,6,9,10}; // pins of anodes
int current_led = 1; // current ON led
int current_loop = 0; // current loop

int delays[] = {1,20,50,100,150,100,50,20};


unsigned long previousMillis = 0;
unsigned long previousLoop = 0;

// Convert binary coded decimal to normal decimal numbers


byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}

// switch on a single led (switch off all other)


void led_on(int index) {
int myAnode = (index - 1) / 5;
int myCathode = (index - 1) % 5;

for (int i = 0; i < 5; i++) {


digitalWrite(anodes[i], LOW);
digitalWrite(cathods[i], HIGH);
}

digitalWrite(anodes[myAnode], HIGH);
digitalWrite(cathods[myCathode], LOW);

// get day of month from RTC clock


byte get_day() {
byte second;
byte minute;
byte hour;
byte dayOfWeek;
byte dayOfMonth;
byte month;
byte year;
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
second = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read() & 0x3f);
dayOfWeek = bcdToDec(Wire.read());
dayOfMonth = bcdToDec(Wire.read());
return dayOfMonth;
}
// play music switching on leds until the one of today
void play(byte today) {

// jingle bells

int melody[] = {
NOTE_E3, NOTE_E3, NOTE_E3,
NOTE_E3, NOTE_E3, NOTE_E3,
NOTE_E3, NOTE_G3, NOTE_C3, NOTE_D3,
NOTE_E3,
NOTE_F3, NOTE_F3, NOTE_F3, NOTE_F3,
NOTE_F3, NOTE_E3, NOTE_E3, NOTE_E3, NOTE_E3,
NOTE_E3, NOTE_D3, NOTE_D3, NOTE_E3,
NOTE_D3, NOTE_G3,
NOTE_E3, NOTE_E3, NOTE_E3,
NOTE_E3, NOTE_E3, NOTE_E3,
NOTE_E3, NOTE_G3, NOTE_C3, NOTE_D3,
NOTE_E3,
NOTE_F3, NOTE_F3, NOTE_F3, NOTE_F3,
NOTE_F3, NOTE_E3, NOTE_E3, NOTE_E3, NOTE_E3,
NOTE_G3, NOTE_G3, NOTE_F3, NOTE_D3,
NOTE_C3
};

// note durations: 4 = half note 2 = quarter note, 1 = eighth note, etc.:


int noteDurations[] = {2,2,4, 2,2,4, 2,2,3,1, 8, 2,2,3,1, 2,2,2,1,1, 2,2,2,2, 4,4, 2,2,4, 2,2,4,
2,2,3,1, 8, 2,2,2,2, 2,2,2,1,1, 2,2,2,2, 8};

// play music
for (int thisNote = 0; thisNote < 51; thisNote++) {

led_on((thisNote % today)+1);

// every quarter lasts 250 ms


int noteDuration = noteDurations[thisNote]*125;
tone(SPEAKER, melody[thisNote],noteDuration);

// to distinguish the notes, set a minimum time between them.


// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(SPEAKER);

// stop music on button press


int sensorVal = digitalRead(BUTTON);
if (sensorVal == LOW) {
Serial.println("Button pressed, stopping music");
delay(300);
// stop the tone playing:
noTone(SPEAKER);
break;
}

// setup
void setup() {
Wire.begin();
Serial.begin(9600);
pinMode(BUTTON, INPUT_PULLUP);
// switch off all
for (int i = 0; i < 5; i++) {
pinMode(cathods[i], OUTPUT);
pinMode(anodes[i], OUTPUT);
digitalWrite(cathods[i], LOW);
digitalWrite(anodes[i], LOW);
}
}

// loop
void loop() {

byte today = get_day();


unsigned long currentMillis = millis();
int loop_interval = 3000;

int myDelay = delays[current_loop];

if (myDelay == 1) {
loop_interval = 5000;
} else {
loop_interval = myDelay * today * 5;
}
// play song on press button
int sensorVal = digitalRead(BUTTON);
if (sensorVal == LOW) {
Serial.println("Button pressed, starting music");
play(today);
}

// different led in the loop (stay "myDelay" on)


if (currentMillis - previousMillis >= myDelay) {
led_on(current_led);
current_led ++;
if (current_led > today) {
// start over after today
current_led = 1;
}
previousMillis = currentMillis;
}
// different loops
if (currentMillis - previousLoop >= loop_interval) {
current_loop ++;
if (current_loop > LOOPS) {
// start over from first loop
current_loop = 0;
}
previousLoop = currentMillis;
}

101) Arduino DIY Code Red Button for Healthcare Simulation


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Adafruit 16mm Illuminated


Pushbutton On/Off × 1

Adafruit Super Bright Red LED


5mm
× 3

Adafruit 5mm Plastic Flat LED


Holder × 3

Adafruit Hook-Up Wire Spool Set


× 1

Adafruit 5V 2A Switching Power


Supply × 1

Adafruit Perma-Proto Quarter-sized


Breadboard PCB × 1

Adafruit Nylon Screws


× 8
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Ultimaker 3

ABOUT THIS PROJECT

DIY CODE RED BUTTON


For those that work in healthcare simulation, we can often find
ourselves trying to simulate different events or procedures. This DIY
code red button can be used in lieu of a real wall button. Follow these
steps:
This is an advanced project that requires the use of multiple pieces
of equipment. Gather all necessary supplies and equipment.
If you own a 3D printer, print the attached CAD files. If not, you
order locally from 3DHubs.
Screw Arduino Uno board into back panel using nylon screws. Be
careful not to apply too much force.
Assemble the front plate and code red plate. Push the 5mm plastic
flat LED holder into the 3 holes on the front plate. Glue code red
plate in place, allow time for glue to dry.

Front Plate with LED Holders in place


Assemble Electronics
This is the electronics assembly part. Get your soldering iron ready
with all the required components. Get your Perma-Proto breadboard
and attach the resistors. Solder in place.

Attach resistors
Start hooking up wires for connection to the LEDs and pushbutton
On/Off. Solder wire connections to the LEDs, use heat-shrink tubing if
needed.
Attach the push button On/Off switch. It does not need to be glued in
place.
Place the LEDs into the flat LED holder through the back of the front
plate. They will snap into place.
Connect both front and back panel. Power using Arduino cable or 9v
battery. Push button, enjoy!

SCHEMATICS
CODE

/*
DIY Code Red Button
Created by David Escobar
Date: 04/14/17
*/

int ledOn = 4; //LED Button On


int led1 = 5; //LED 1
int led2 = 6; //LED 2
int led3 = 7; //LED 3

void setup() {
pinMode(ledOn, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}

void loop() {

blink();
}

void blink(){
digitalWrite(ledOn, HIGH);
digitalWrite(led1, HIGH);
digitalWrite(led2, HIGH);
digitalWrite(led3, HIGH);
delay(250);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
delay(100);
}

102) Arduino Fix Ice Making Machine


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Relay (generic)
× 1
NECESSARY TOOLS AND MACHINES
Old Ice Maker
APPS AND ONLINE SERVICES
Arduino IDE

ardublock

ABOUT THIS PROJECT

My Ice Maker
arduino and relays
Ice maker in operation

SCHEMATICS
CODE

void setup()
{
pinMode( 4 , INPUT);
pinMode( 5 , INPUT);
pinMode( 6 , INPUT);
pinMode( 4 , OUTPUT);
pinMode( 5 , OUTPUT);
pinMode( 6 , OUTPUT);
pinMode( 8 , OUTPUT);
pinMode( 9 , OUTPUT);
pinMode( 10 , OUTPUT);
pinMode( 11 , OUTPUT);
digitalWrite( 4 , LOW );

digitalWrite( 5 , LOW );

digitalWrite( 6 , LOW );

digitalWrite( 8 , HIGH );

digitalWrite( 9 , HIGH );

digitalWrite( 10 , HIGH );

digitalWrite( 11 , HIGH );

void loop()
{
if ( digitalRead( 4))
{
digitalWrite( 8 , LOW );
}
if ( digitalRead( 5))
{
digitalWrite( 8 , HIGH );
digitalWrite( 9 , LOW );
delay( 40000 );
digitalWrite( 9 , HIGH );
digitalWrite( 10 , LOW );
delay( 700000 );
digitalWrite( 8 , LOW );
delay( 5000 );
}
if ( digitalRead( 6))
{
digitalWrite( 8 , HIGH );
delay( 5000 );
digitalWrite( 11 , LOW );
delay( 30000 );
digitalWrite( 11 , HIGH );
digitalWrite( 8 , LOW );
delay( 10000 );
}
}

103) Arduino Based Graph


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Rotary potentiometer (generic)

× 1

ABOUT THIS PROJECT


This shows you how to send a byte of data from the Arduino or Genuino
to a personal computer and graph the result. This is called serial
communication because the connection appears to both the board and the
computer as a serial port, even though it may actually use a USB cable, a
serial to USB and a USB to serial converter.
You can use the serial monitor of the Arduino Software (IDE) to view the
sent data, or it can be read by Processing (see code below), Flash, PD,
Max/MSP, etc.
Circuit
Connect a potentiometer or other analog sensor to analog input 0.

Schematic
Code
/* Graph
A simple example of communication from the Arduino board to the
computer: The value of analog input 0 is sent out the serial port. We call
this "serial" communication because the connection appears to both the
Arduino and the computer as a serial port, even though it may actually
use a USB cable. Bytes are sent one after another (serially) from the
Arduino to the computer.
You can use the Arduino Serial Monitor to view the sent data, or it can
be read by Processing, PD, Max/MSP, or any other program capable of
reading data from a serial port. The Processing code below graphs the
data received so you can see the value of the analog input changing over
time.
The circuit: - any analog input sensor attached to analog in pin 0*/
void setup() { // initialize the serial communication: Serial.begin(9600);}
void loop() { // send the value of analog input 0:
Serial.println(analogRead(A0)); // wait a bit for the analog-to-digital
converter to stabilize after the last // reading: delay(2);}
/* Processing code for this example
// Graphing sketch
// This program takes ASCII-encoded strings from the serial port at 9600
baud // and graphs them. It expects values in the range 0 to 1023,
followed by a // newline, or newline and carriage return
import processing.serial.*;
Serial myPort; // The serial port int xPos = 1; // horizontal
position of the graph float inByte = 0;
void setup () { // set the window size: size(400, 300);
// List all the available serial ports // if using Processing 2.1 or later,
use Serial.printArray() println(Serial.list());
// I know that the first port in the serial list on my Mac is always my //
Arduino, so I open Serial.list()[0]. // Open whatever port is the one
you're using. myPort = new Serial(this, Serial.list()[0], 9600);
// don't generate a serialEvent() unless you get a newline character:
myPort.bufferUntil('\n');
// set initial background: background(0); }
void draw () { // draw the line: stroke(127, 34, 255); line(xPos,
height, xPos, height - inByte);
// at the edge of the screen, go back to the beginning: if (xPos >=
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.3oc0YszbaaCD9r7uBL5RalQUAO3CvdyS5zVenWZxs5NcfHgjPCIfJITRTxj+6
----------end_max5_patcher-----------
*/
Processing Sketch
Using the Processing sketch in the code sample above, you'll get a graph
of the sensor's value. As you change the value of the analog sensor, you'll
get a graph something like this:

SCHEMATICS
CODE
/* Graph

A simple example of communication from the Arduino board to the


computer: The
value of analog input 0 is sent out the serial port. We call this "serial"
communication because the connection appears to both the Arduino and
the
computer as a serial port, even though it may actually use a USB cable.
Bytes
are sent one after another (serially) from the Arduino to the computer.

You can use the Arduino Serial Monitor to view the sent data, or it can be
read by Processing, PD, Max/MSP, or any other program capable of
reading data
from a serial port. The Processing code below graphs the data received so
you
can see the value of the analog input changing over time.

The circuit:
- any analog input sensor attached to analog in pin 0
*/

void setup() {
// initialize the serial communication:
Serial.begin(9600);
}

void loop() {
// send the value of analog input 0:
Serial.println(analogRead(A0));
// wait a bit for the analog-to-digital converter to stabilize after the last
// reading:
delay(2);
}

/* Processing code for this example

// Graphing sketch

// This program takes ASCII-encoded strings from the serial port at 9600
baud
// and graphs them. It expects values in the range 0 to 1023, followed by a
// newline, or newline and carriage return

import processing.serial.*;

Serial myPort; // The serial port


int xPos = 1; // horizontal position of the graph
float inByte = 0;

void setup () {
// set the window size:
size(400, 300);

// List all the available serial ports


// if using Processing 2.1 or later, use Serial.printArray()
println(Serial.list());

// I know that the first port in the serial list on my Mac is always my
// Arduino, so I open Serial.list()[0].
// Open whatever port is the one you're using.
myPort = new Serial(this, Serial.list()[0], 9600);

// don't generate a serialEvent() unless you get a newline character:


myPort.bufferUntil('\n');

// set initial background:


background(0);
}

void draw () {
// draw the line:
stroke(127, 34, 255);
line(xPos, height, xPos, height - inByte);

// at the edge of the screen, go back to the beginning:


if (xPos >= 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

HC-05 Bluetooth Module

× 1

L293D MOTOR DRIVERS


× 5

Arduino Mega 2560 & Genuino


Mega 2560
× 1

DC motor (generic)
× 2

BASE AS CAR CHASIS


× 1

9V battery (generic)

× 3
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
× 1
Any Arduino based card will
work
Adafruit RGB Backlight LCD -
16x2
× 1
Any type of readable display
device
Analog joystick (Generic)
The Joystick you select must have
Infrared Capabilities, but you may × 1
also use almost any Infrared
remote device.
Solderless Breadboard Full Size

× 2

Jumper wires (generic)

× 1

Resistor 10k ohm

× 2

IR receiver (generic)
Be sure to check if you need to
× 1
install an inline resistor. Some
have them built in.
Single Turn Potentiometer- 10k
ohms
× 2
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 <IRremote.h>
#include <LiquidCrystal.h>

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

LED (generic)
Any color
× 3

Temperature Sensor

× 1

Jumper wires (generic)

× 16
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

× 1

2.8 inch TFT Touch LCD screen


× 1

Li-Po Rechargeable Battery


600mAh 3.7v (30mm x 50mm x
6mm maximum physical × 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 <Adafruit_GFX.h> // Core graphics library


#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>
#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)) { // Row 1


touchlocation = 1;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 2;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 3;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 4;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 5;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 6;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 7;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 8;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 9;
}
} else
if ((p.x > 28) && (p.x < 53)) { // Coloumn 2

if ((p.y > 0) && (p.y < 27)) { // Row 1


touchlocation = 10;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 11;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 12;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 13;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 14;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 15;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 16;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 17;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 18;
}

} else
if ((p.x > 54) && (p.x < 80)) { // Coloumn 3

if ((p.y > 0) && (p.y < 27)) { // Row 1


touchlocation = 19;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 20;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 21;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 22;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 23;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 24;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 25;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 26;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 27;
}

} else
if ((p.x > 81) && (p.x < 107)) { // Coloumn 4

if ((p.y > 0) && (p.y < 27)) { // Row 1


touchlocation = 28;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 29;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 30;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 31;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 32;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 33;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 34;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 35;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 36;
}

} else
if ((p.x > 108) && (p.x < 133)) { // Coloumn 5

if ((p.y > 0) && (p.y < 27)) { // Row 1


touchlocation = 37;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 38;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 39;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 40;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 41;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 42;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 43;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 44;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 45;
}

} else
if ((p.x > 134) && (p.x < 160)) { // Coloumn 6

if ((p.y > 0) && (p.y < 27)) { // Row 1


touchlocation = 46;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 47;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 48;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 49;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 50;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 51;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 52;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 53;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 54;
}

} else
if ((p.x > 161) && (p.x < 187)) { // Coloumn 7

if ((p.y > 0) && (p.y < 27)) { // Row 1


touchlocation = 55;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 56;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 57;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 58;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 59;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 60;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 61;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 62;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 63;
}

} else
if ((p.x > 188) && (p.x < 213)) { // Coloumn 8

if ((p.y > 0) && (p.y < 27)) { // Row 1


touchlocation = 64;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 65;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 66;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 67;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 68;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 69;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 70;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 71;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 72;
}
} else
if ((p.x > 214) && (p.x < 240)) { // Coloumn 9
if ((p.y > 0) && (p.y < 27)) { // Row 1
touchlocation = 73;
}
if ((p.y > 28) && (p.y < 53)) { // Row 2
touchlocation = 74;
}
if ((p.y > 54) && (p.y < 80)) { // Row 3
touchlocation = 75;
}
if ((p.y > 81) && (p.y < 107)) { // Row 4
touchlocation = 76;
}
if ((p.y > 108) && (p.y < 133)) { // Row 5
touchlocation = 77;
}
if ((p.y > 134) && (p.y < 160)) { // Row 6
touchlocation = 78;
}
if ((p.y > 161) && (p.y < 187)) { // Row 7
touchlocation = 79;
}
if ((p.y > 188) && (p.y < 213)) { // Row 8
touchlocation = 80;
}
if ((p.y > 214) && (p.y < 240)) { // Row 9
touchlocation = 81;
}

// 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(" ");

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]);

*/

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(" ");

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]);

*/

}
}

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(" ");

Serial.print(tempcount); 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(" ");

Serial.print(tempcount); 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
× 1

DFRobot I2C 16x2 Arduino LCD


Display Module
× 1

Buzzer

× 1

IR receiver (generic)
× 1

JustBoom IR Remote

× 1

Seeed Pi RTC (DS1307)

× 1

Jumper wires (generic)

× 1

Resistor 10k ohm

× 1
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 <IRremote.h>
#include <IRremoteInt.h>
#include <LiquidCrystal.h>
#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 <stdlib.h>
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()<10)lcd.print("0");
lcd.print(now.hour());
lcd.print(':');
if(now.minute()<10)lcd.print("0");
lcd.print(now.minute());
lcd.print(':');
if(now.second()<10)lcd.print("0");
lcd.print(now.second());
lcd.print(" ");
getAlarm();
}
void getAlarm(){
int ques1 = rand()%100+1;
int ques2 = rand()%100+1;
int ans = ques1 + ques2;
if (irrecv.decode(&results)){
Serial.println(results.value, HEX);
irrecv.resume();
if(results.value==0xFFB04F){
setAlarm=1;
}else if(results.value==0xFFFFFFFF){
setAlarm = setAlarm;
}
}
if(digitalRead(buzzerPin)==HIGH){
setAlarm=5;
}
while(setAlarm==1){
lcd.setCursor(0,0);
lcd.print("Set Hour");
lcd.setCursor(0,1);
if(irrecv.decode(&results)){
for(int i = 0; i<10; i++){
if(results.value==num[i]){
a = a*10+i;
}else if(results.value==0xFFFFFFFF){
a = a;
}
irrecv.resume();
}
if(a<24){
lcd.print(a);
if(results.value==0xFFB04F){
setAlarm=2;
}
}else{
lcd.clear();
setAlarm = 1;
a=0;
}
}
}
while(setAlarm==2){
lcd.setCursor(0,0);
lcd.print("Set Minute");
lcd.setCursor(0,1);
if(irrecv.decode(&results)){
for(int i = 0; i<10; i++){
if(results.value==num[i]){
b = b*10+i;
}else if(results.value==0xFFFFFFFF){
b = b;
}else if(results.value==0xFFB04F){
setAlarm++;
}
irrecv.resume();
}
lcd.print(a);
lcd.print(':');
if(b<60){
lcd.print(b);
if(results.value==0xFFB04F){
setAlarm=3;
}
}else{
lcd.clear();
setAlarm = 2;
b=0;
}
}
}
while(setAlarm==3){
lcd.setCursor(0,0);
lcd.print("Set Second");
lcd.setCursor(0,1);
if(irrecv.decode(&results)){
for(int i = 0; i<10; i++){
if(results.value==num[i]){
c = c*10+i;
}else if(results.value==0xFFFFFFFF){
c = c;
}else if(results.value==0xFFB04F){
setAlarm++;
}
irrecv.resume();
}
lcd.print(a);
lcd.print(':');
lcd.print(b);
lcd.print(':');
if(c<60){
lcd.print(c);
if(results.value==0xFFB04F){
setAlarm=4;
}
}else{
lcd.clear();
setAlarm = 3;
c=0;
}
}
}
while(setAlarm==4){
lcd.setCursor(0,1);
lcd.print("Alarm-");
if(a<10)lcd.print("0");
lcd.print(a);
lcd.print(':');
if(b<10)lcd.print("0");
lcd.print(b);
lcd.print(':');
if(c<10)lcd.print("0");
lcd.print(c);
if(results.value==0xFFB04F){
setAlarm=0;
}
}
DateTime now = rtc.now();
if(now.hour()==a && now.minute()==b && now.second()==c){
tone(buzzerPin, 100);
a=0;
b=0;
c=0;
}
if(irrecv.decode(&results)){
if(results.value==0xFFA25D){
a=0;
b=0;
c=0;
lcd.setCursor(0,1);
lcd.clear();
}
}
while(setAlarm==5){
lcd.setCursor(0,0);
lcd.print(ques1);
lcd.print('+');
lcd.print(ques2);
lcd.print(" ");
if(irrecv.decode(&results)){
for(int i = 0; i<10; i++){
if(results.value==num[i]){
d = d*10+i;
}else if(results.value==0xFFA25D){
d=0;
lcd.print(" ");
}
irrecv.resume();
}
lcd.print(d);
}
if(d==ans){
noTone(buzzerPin);
setAlarm=0;
lcd.setCursor(0,1);
lcd.clear();
d=0;
}
}
}
109) Arduino Gesture Mouse
COMPONENTS AND SUPPLIES
Arduino Leonardo

× 1

GY-521 MPU-6050 3 Axis


Gyroscope + Accelerometer
Module For Arduino × 1

SparkFun Pushbutton switch 12mm


× 1

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Adafruit Joystick
× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

1. Leonardo:
Arduino Leonardo is an old board but the only compatible board for
this project. It has the required SCL and SDA pin for connection of
MPU6050.
Connections: Connect the 5V and GND to breadboard.
2. Joystick:
Use: We use the joystick as a keyboard. While playing a game,we use it
move the character in front or back or sideways,etc.
Connections: Connect the GND and 5V in the same line as that of
Leonardo as shown in the schematics. Connect the VRX to A1 (Analog
Pin 1) and VRY to A0 of Leonardo.
3. MPU6050:
Use: The MPU6050 is a 6 DOF (Degrees of Freedom) or a six axis
IMU sensor, which means that it gives six values as output. Three
values from the accelerometer and three from the gyroscope. It is
basically used as a mouse.
Connections: Connect the GND and VCC in the railing as in
schematics. Connect the SCL and SDA to SCL and SDA of Leonardo.
4. Button:
Use: Used as a fire button while playing any game.
Connections: Connect the button pin to Digital Pin 1 and other to GND.
Connect everything according to the schematics. Upload the code to
Leonardo and watch the fun!
Note: To switch on the joystick, press it down once.
SCHEMATICS

CODE
#include <Keyboard.h>
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>
#include <Mouse.h>
#define LBUT 7
#define RBUT 5

int xPin = A1;


int yPin = A0;
int buttonPin = 1;

int xPosition = 0;
int yPosition = 0;
int buttonState = 0;
MPU6050 mpu;
int16_t ax, ay, az, gx, gy, gz;
int angleToDistance(int a)
{
if (a < -80)
{
return -40;
}
else if (a < -65) {
return -20;
}
else if (a < -50) {
return -10;
}
else if (a < -15) {
return -5;
}
else if (a < -5) {
return -1;
}
else if (a > 80) {
return 40;
}
else if (a > 65) {
return 20;
}
else if (a > 15) {
return 10;
}
else if (a > 5) {
return 1;
}
}

void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
Keyboard.begin();
Mouse.begin();

pinMode(xPin, INPUT);
pinMode(yPin, INPUT);

//activate pull-up resistor on the push-button pin


pinMode(buttonPin, INPUT_PULLUP);

// For versions prior to Arduino 1.0.1


// pinMode(buttonPin, INPUT);
// digitalWrite(buttonPin, HIGH);
// put your setup code here, to run once:
pinMode(LBUT, INPUT);
digitalWrite(LBUT, HIGH);
pinMode(RBUT, INPUT);
digitalWrite(RBUT, HIGH);
Wire.begin();
mpu.initialize();
if (!mpu.testConnection()) {
while (1);
}
}
void loop() {
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
int vx = map(ax, -16000, 16000, 90, -90);
int vy = map(ay, -16000, 16000, 90, -90);
attachInterrupt(1, keyboard, CHANGE);
attachInterrupt(7,fire,HIGH);
Mouse.move(angleToDistance(vx), angleToDistance(vy));
if (digitalRead(LBUT) == LOW) {
if (!Mouse.isPressed(MOUSE_LEFT)) {
Mouse.press(MOUSE_LEFT);
}
}
else {
if (Mouse.isPressed(MOUSE_LEFT)) {
Mouse.release(MOUSE_LEFT);
}
}
if (digitalRead(RBUT) == LOW) {
if (!Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.press(MOUSE_RIGHT);
}
}
else {
if (Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.release(MOUSE_RIGHT);
}
}
delay(20);
xPosition = analogRead(xPin);
yPosition = analogRead(yPin);
buttonState = digitalRead(buttonPin);
Serial.print("X: ");
Serial.print(xPosition);
Serial.print(" | Y: ");
Serial.print(yPosition);
Serial.print(" | Button: ");
Serial.println(buttonState);

// delay(100); // add some delay between reads

if (yPosition < 10)


{
Keyboard.releaseAll();
Keyboard.press('w'); //for w
Keyboard.releaseAll();
}
if (yPosition < 700 && yPosition > 600||yPosition>1020)
{
Keyboard.releaseAll();
Keyboard.press('s'); //for s
Keyboard.releaseAll();

if (xPosition < 10)


{

Keyboard.releaseAll();

Keyboard.press('a'); //for a
Keyboard.releaseAll();
}

if (xPosition < 700 && xPosition > 600||xPosition>1020)


{
Keyboard.releaseAll();

Keyboard.press('d'); //for d
Keyboard.releaseAll();
}
}
void keyboard()
{
xPosition = analogRead(xPin);
yPosition = analogRead(yPin);
buttonState = digitalRead(buttonPin);
Serial.print("X: ");
Serial.print(xPosition);

Serial.print(" | Y: ");
Serial.print(yPosition);
Serial.print(" | Button: ");
Serial.println(buttonState);

//delay(100); // add some delay between reads

if (yPosition < 10)


{
Keyboard.releaseAll();
Keyboard.press('w'); //for w
Keyboard.releaseAll();
}
if (yPosition < 700 && yPosition > 600||yPosition>1020)
{
Keyboard.releaseAll();
Keyboard.press('s'); //for s
Keyboard.releaseAll();

if (xPosition < 10)


{

Keyboard.releaseAll();

Keyboard.press('a'); //for a
Keyboard.releaseAll();
}

if (xPosition < 700 && xPosition > 600||xPosition>1020)


{
Keyboard.releaseAll();
Keyboard.press('d'); //for d
Keyboard.releaseAll();

}
}
void fire()
{

110) A Power Router to Optimize Homemade Electricity with


Arduino
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

DFRobot I2C 16x2 Arduino LCD


Display Module
× 1

Pushbutton Switch, Momentary


× 3
NECESSARY TOOLS AND MACHINES
Digilent Mastech MS8217 Autorange Digital
Multimeter
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Or how to make a Power Router to optimize homemade electricity


consumption and to prevent against public grid injection.
Are your tired to offer to your electricity grid provider any surplus of
your own electricity you produce?Would you prefer either to switch on
a machine to consume this surplus, or to switch off a (micro) invertor
so that exceeded energy will only charge batteries?And so this would
be done automatically?
A Power Router is a device that will detect any injection in public
power grid and help to prevent against it.This manual explains step by
step how to build this device, with an Arduino Uno rev.3.
The device detects the current at the immediate entrance of the public
power grid, and the voltage on the line.Any injection in the public
power grid is detected by the shift between current and voltage:When
“in same way” we are consuming. When “in opposite way” we are
injecting.
Then the power consumption is calculated and the Triac is driven by
the device in order to prevent any injection. Parameters allow to fix
limit values.
In addition a load shedding is possible that will switch on or off any
device, depending of the consumption. For instance a SSR can cut off
the wind turbine injection (and then it will charge batteries only) if
consumption is near 0 (near injection in grid) and will be switched on
again once consumption raises the power delivered by the wind turbine
invertor.

SCHEMATICS
CODE
/*

A Power Router is a device that detects any homemade electrical energy in exceed. If so
several actions can be taken :
- with the Triac function: gradually switch on a resistive load that will take all the
exceed energy. This load must be resistive (edison light, water heat, etc...) due to
the power factor which must stay near 1.
- with the SSR function: prevent against any exceed by performing a load shedding : just
before injection in the public power grid, either a load can be add to increase
consumtion, or a power generator (solar panel, wind turbine) can be stopped.

The operation is performed by:


- a shift detection between the grid current and the voltage which detect a power
consumption
or a power injection.
- in case of injection it initiates the gradual absorption by a resistive load of any exceed
power
- the current measure allows the absorption adjustment
- a load shedding becomes active when the system is very near injection and automatically
stops as soon as a level of consumption is raised.

This device is actually in operation in two homes with a power load of 350W and 1000W.

Materials :
1* Arduino Uno R3 - IDE version 1.8.7
1* AC current sensor 20A/25mA
1* AC-AC 230V-2.5V transformer
1* LCD 1602 with I2C extension
1* shield : see manual documentation for wiring implementation
1* triac dimming module with zero-cross detection
3* push-buttons
1* SSR + 1* transistor NPN, 1* transistor PNP, few resistors, capacitors...

Pinup :
- pin A0 (analog 0) => AC current sensor
- pin A1 (analog 1) => AC voltage sensor
- pin A4 (analog 4) => SDA output for LCD
- pin A5 (analog 5) => SCL output for LCD
- pin 2 (numeric 2) => 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 <EEPROM.h>
#include <avr/wdt.h> // documentation: https://tushev.org/articles/arduino/5/arduino-and-
watchdog-timer
#include <TimerOne.h> // library to install:
http://www.arduino.cc/playground/Code/Timer1
#include <LiquidCrystal_I2C.h> // https://github.com/fdebrabander/Arduino-
LiquidCrystal-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/external-
interrupts/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 << 8) + reboot_low;
reboot++;
EEPROM.update(0, highByte(reboot));
EEPROM.update(1, lowByte(reboot));

// EEPROM functions are used to store parameters


if(EEPROM.read(2) < 200) limitP = EEPROM.read(2); else EEPROM.write(2, limitP);
if(EEPROM.read(3) < 50) delestON = EEPROM.read(3); else EEPROM.write(3,
delestON);
unsigned char delestOFF_high = EEPROM.read(4);
unsigned char delestOFF_low = EEPROM.read(5);
int delestOFF_full = (delestOFF_high << 8) + delestOFF_low;
if( delestOFF_full < 10001 ) delestOFF = delestOFF_full;
else {
EEPROM.write(4, highByte(delestOFF));
EEPROM.write(5, lowByte(delestOFF));
}
if(EEPROM.read(6) < 2) etat_delest_repos = EEPROM.read(6); else EEPROM.write(6,
etat_delest_repos);
if(EEPROM.read(7) < 255) reactancelevel = EEPROM.read(7); else EEPROM.write(7,
reactancelevel);
if(EEPROM.read(8) < 31) phasecalibration = (EEPROM.read(8))/10.0; else
EEPROM.write(8, (phasecalibration*10));

// LCD initialisation
lcd.begin(); // initialize the lcd for 16 chars 2 lines
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("POWER ROUTER");
lcd.setCursor(0, 1);
lcd.print("is starting !");

// console initialisation
Serial.begin(250000);
Serial.println ();
Serial.print("PLEASE NOTE : ");
Serial.print(reboot);
Serial.println(" total number of reboots");
Serial.println();
Serial.println("Ready to start ...");
Serial.println ();
delay(500);
if( VERBOSE == true ) Serial.print(" Pu (W) || dimstep | dim || load shedding");
else Serial.println("It is working now !");
Serial.println();

digitalWrite(delestPin, etat_delest_repos); // state output to the default load shedding state


wdt_enable(WDTO_500MS); // watchdog = reset if no activity longer than
500ms

} // End setup
//
// ZERO CROSS DETECT : zero-cross interrupt
//_____________________________________________________________________________________

void zero_cross_detect() { // this function is called at each zero-cross interrupt


zero_cross_flag = true; // flag for the real power calculation
zero_cross = true; // flag to drive the Triac
}

//
// DIM CHECK : drive the Triac
//_____________________________________________________________________________________

void dim_check() { // Function will fire the triac at the proper time
if(zero_cross == true && dim < dimmax) // First check to make sure the zero-cross has
{ // happened else do nothing
if(i>dim) { // i is a counter that defines the fire delay. higher is dim longer i will
count
digitalWrite(triacPin, HIGH); // and later the triac will fire
delayMicroseconds(50); // Pause briefly to ensure the triac turned on
digitalWrite(triacPin, LOW); // Turn off the Triac gate, but the triac stays switch on
until OV
i = 0; // Reset the counter for the next cycle
zero_cross = false;
}
else i++; // If the dimming value has not been reached, increase it
} // End zero_cross check
} // End dim_check function

//
// LOOP
//_____________________________________________________________________________________

void loop() { // Main Loop

// 1st part: calculation of the real electric power rPower


//_____________________________________________________________________________________
//

unsigned int numberOfSamples = 0;


sumV = 0;
sumI = 0;
sumP = 0;
unsigned int temps_actuel = millis()/1000; // get the time spent in seconds
// increment zero_crossCount at each zero-cross until totalCount, then rPower value is
calculated

if( zero_crossCount >= 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); // overload LED


else { digitalWrite(limitLedPin, LOW); }
analogWrite(triacLedPin, dimmax-dim); // Write the value to the LED for testing

// load shedding management


if( rPower > -delestON) { delestage = true; } // threshold activation value for load
shedding

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

2.5mm stereo plug


× 1

5.1V Zener diode


× 1

General Purpose Transistor NPN


and two resistors
× 1
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 LANC<->RS232 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<24 ;i++) { // Write back LANC message over serial
Serial.print(outString[i]);
}
Serial.print('\n');
}
else {
Serial.println("Faulty input!");
}

for (int i=0 ; i<5 ; i++) { // Clear input array


inString[i] = 0;
}
strComplete = false; // Reset data received flag
}

void bitarraytohexchar() {
// The bit array lancMessage contains the whole LANC message (8 bytes) with LSB first
// This function converts them to hex chars and stores them in outString (16 chars)

byte temp = 0;

for ( int i=0 ; i<8 ; i++) { // Byte loop

for ( int j=0 ; j<4 ; j++) { // Bit loop


temp += (pow2(j) * lancMessage[(j+4)+i*8]);
}
outString[i*3] = bytetohexchar(temp);
temp = 0;

for ( int j=0 ; j<4 ; j++) { // Bit loop


temp += (pow2(j) * lancMessage[j+i*8]);
}
outString[i*3+1] = bytetohexchar(temp);
outString[i*3+2] = ' ';
temp = 0;
}

outString[24] = '\n';

boolean hexchartobitarray() {
// The hex code in char (4 chars) is located in inString
// This function fills the lancCmd array with the bits in the order they should be sent
// First byte 1 then byte 2 but with LSB first for both bytes

int byte1, byte2;

for (int i = 0 ; i < 4 ; i++ ) {


if (!(isHexadecimalDigit(inString[i]))) {
return 0;
}
}

byte1 = (hexchartoint(inString[0]) << 4) + hexchartoint(inString[1]);


byte2 = (hexchartoint(inString[2]) << 4) + hexchartoint(inString[3]);

for (int i = 0 ; i < 8 ; i++ ) {


lancCmd[i] = bitRead(byte1,i); // Reads one bit from a number, x is number, n is
position (0 is LSB)
}
for (int i = 0 ; i < 8 ; i++ ) {
lancCmd[i + 8] = bitRead(byte2,i); // Reads one bit from a number, x is number, n is
position (0 is LSB)
}

return 1;
}

void sendLanc(byte repeats) {


// This function is time critical and optimized for Arduino Pro Mini
// It takes ~3.2us for the arduino to set a pin state with the digitalWrite command
// It takes ~80ns for the arduino to set pin state using the direct register method
// delayMicroseconds(50) ~ 49us, delayMicroseconds(100) ~ 99us

int i = 0;
int bytenr = 0;

while (pulseIn(lancPin, HIGH) < 5000) {


// Sync to next LANC message
// "pulseIn, HIGH" catches any 0V TO +5V TRANSITION and waits until the LANC line
goes back to 0V
// "pulseIn" also returns the pulse duration so we can check if the previous +5V duration
was long enough (>5ms) to be the pause before a new 8 byte data packet
}

while (repeats) {

i = 0;
bytenr = 0;

ledON; // LANC message LED indicator on

for ( ; bytenr<8 ; bytenr++) {


delayMicroseconds(bitDura-7); // LOW after long pause means the START bit of
Byte 0 is here, wait START bit duration
for ( ; i<(8*(bytenr+1)) ; i++) {
if (bytenr<2) {
if (lancCmd[i]) { // During the first two bytes the adapter controls the line and
puts out data
cmdPinON;
}
else {
cmdPinOFF;
}
}
delayMicroseconds(halfbitDura);
lancMessage[i] = !lancPinREAD; // Read data line during middle of bit
delayMicroseconds(halfbitDura);
}
cmdPinOFF;
if (bytenr == 7) {
ledOFF;
}
delayMicroseconds(halfbitDura); // Make sure to be in the stop bit before waiting for
next byte
while (lancPinREAD) { // Loop as long as the LANC line is +5V during the
stop bit or between messages
}
}
repeats--;
}
}

/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
*/
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read(); // Get the new byte
inString[strPointer++] = inChar; // Add it to the input string
if ((inChar == '\n') || (inChar == '\r') || (strPointer > 4)) { // If the incoming character is a
newline, carriage return or 4 bytes has been received flag so the main loop can act
strComplete = true;
strPointer = 0;
}
}
}

int pow2(int x) {
switch (x) {
case 0:
return 1;
break;
case 1:
return 2;
break;
case 2:
return 4;
break;
case 3:
return 8;
break;
case 4:
return 16;
break;
case 5:
return 32;
break;
case 6:
return 64;
break;
case 7:
return 128;
break;
default:
return 0;
break;
}
}

char bytetohexchar(byte hexbyte) {


switch (hexbyte) {
case 15:
return 'F';
break;
case 14:
return 'E';
break;
case 13:
return 'D';
break;
case 12:
return 'C';
break;
case 11:
return 'B';
break;
case 10:
return 'A';
break;
default:
return (hexbyte + 48);
break;
}
}

int hexchartoint(char hexchar) {


switch (hexchar) {
case 'F':
return 15;
break;
case 'f':
return 15;
break;
case 'E':
return 14;
break;
case 'e':
return 14;
break;
case 'D':
return 13;
break;
case 'd':
return 13;
break;
case 'C':
return 12;
break;
case 'c':
return 12;
break;
case 'B':
return 11;
break;
case 'b':
return 11;
break;
case 'A':
return 10;
break;
case 'a':
return 10;
break;
default:
return (int) (hexchar - 48);
break;
}
}
112) Arduino Robot Car Project
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

HC-06 Bluetooth Module


× 1
HC 05 may be used.
Arduino 4WD Smart Robot Car
Chassis Kits × 1
SparkFun Dual H-Bridge motor
drivers L298 × 2

LEDs
× 4

Resistor 221 ohm

× 4

Buzzer

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Hot glue gun (generic)


APPS AND ONLINE SERVICES
Arduino IDE

android apps

ABOUT THIS PROJECT

Hi everyone! This is my next project, a smartphone-controlled Arduino


4WD robot car or Bluetooth Arduino robot. It can move forward and
backward, left and right, change its speed, turn on / off front and back
lights and also it can horn.
This is a quite simple design robot you can easily build it.
Step 1: Requirements
Parts Required:
Arduino Uno R3 Board
Chassis 4WD with DC Motor and Wheel x4
Motor Driver L298N x2
Bluetooth module HC-06
Li-ion battery 18650 x2
LEDs + resistors 220 Ohm x4
Buzzer
SCHEMATICS
CODE
#define light_FR 14 //LED Front Right pin A0 for Arduino Uno
#define light_FL 15 //LED Front Left pin A1 for Arduino Uno
#define light_BR 16 //LED Back Right pin A2 for Arduino Uno
#define light_BL 17 //LED Back Left pin A3 for Arduino Uno
#define horn_Buzz 18 //Horn Buzzer pin A4 for Arduino Uno

#define ENA_m1 5 // Enable/speed motor Front Right


#define ENB_m1 6 // Enable/speed motor Back Right
#define ENA_m2 10 // Enable/speed motor Front Left
#define ENB_m2 11 // Enable/speed motor Back Left

#define IN_11 2 // L298N #1 in 1 motor Front Right


#define IN_12 3 // L298N #1 in 2 motor Front Right
#define IN_13 4 // L298N #1 in 3 motor Back Right
#define IN_14 7 // L298N #1 in 4 motor Back Right

#define IN_21 8 // L298N #2 in 1 motor Front Left


#define IN_22 9 // L298N #2 in 2 motor Front Left
#define IN_23 12 // L298N #2 in 3 motor Back Left
#define IN_24 13 // L298N #2 in 4 motor Back Left

int command; //Int to store app command state.


int speedCar = 100; // 50 - 255.
int speed_Coeff = 4;
boolean lightFront = false;
boolean lightBack = false;
boolean horn = false;

void setup() {

pinMode(light_FR, OUTPUT);
pinMode(light_FL, OUTPUT);
pinMode(light_BR, OUTPUT);
pinMode(light_BL, OUTPUT);
pinMode(horn_Buzz, OUTPUT);

pinMode(ENA_m1, OUTPUT);
pinMode(ENB_m1, OUTPUT);
pinMode(ENA_m2, OUTPUT);
pinMode(ENB_m2, OUTPUT);
pinMode(IN_11, OUTPUT);
pinMode(IN_12, OUTPUT);
pinMode(IN_13, OUTPUT);
pinMode(IN_14, OUTPUT);

pinMode(IN_21, OUTPUT);
pinMode(IN_22, OUTPUT);
pinMode(IN_23, OUTPUT);
pinMode(IN_24, OUTPUT);

Serial.begin(9600);

void goAhead(){
digitalWrite(IN_11, LOW);
digitalWrite(IN_12, HIGH);
analogWrite(ENA_m1, speedCar);

digitalWrite(IN_13, HIGH);
digitalWrite(IN_14, LOW);
analogWrite(ENB_m1, speedCar);

digitalWrite(IN_21, HIGH);
digitalWrite(IN_22, LOW);
analogWrite(ENA_m2, speedCar);

digitalWrite(IN_23, LOW);
digitalWrite(IN_24, HIGH);
analogWrite(ENB_m2, speedCar);

void goBack(){

digitalWrite(light_BR, HIGH); digitalWrite(light_BL, HIGH);


digitalWrite(IN_11, HIGH);
digitalWrite(IN_12, LOW);
analogWrite(ENA_m1, speedCar);

digitalWrite(IN_13, LOW);
digitalWrite(IN_14, HIGH);
analogWrite(ENB_m1, speedCar);
digitalWrite(IN_21, LOW);
digitalWrite(IN_22, HIGH);
analogWrite(ENA_m2, speedCar);

digitalWrite(IN_23, HIGH);
digitalWrite(IN_24, LOW);
analogWrite(ENB_m2, speedCar);

void goRight(){

digitalWrite(IN_11, LOW);
digitalWrite(IN_12, HIGH);
analogWrite(ENA_m1, speedCar);

digitalWrite(IN_13, HIGH);
digitalWrite(IN_14, LOW);
analogWrite(ENB_m1, speedCar);

digitalWrite(IN_21, LOW);
digitalWrite(IN_22, HIGH);
analogWrite(ENA_m2, speedCar);

digitalWrite(IN_23, HIGH);
digitalWrite(IN_24, LOW);
analogWrite(ENB_m2, speedCar);

void goLeft(){

digitalWrite(IN_11, HIGH);
digitalWrite(IN_12, LOW);
analogWrite(ENA_m1, speedCar);

digitalWrite(IN_13, LOW);
digitalWrite(IN_14, HIGH);
analogWrite(ENB_m1, speedCar);

digitalWrite(IN_21, HIGH);
digitalWrite(IN_22, LOW);
analogWrite(ENA_m2, speedCar);

digitalWrite(IN_23, LOW);
digitalWrite(IN_24, HIGH);
analogWrite(ENB_m2, speedCar);

void goAheadRight(){

digitalWrite(IN_11, HIGH);
digitalWrite(IN_12, LOW);
analogWrite(ENA_m1, speedCar/speed_Coeff);

digitalWrite(IN_13, LOW);
digitalWrite(IN_14, HIGH);
analogWrite(ENB_m1, speedCar/speed_Coeff);

digitalWrite(IN_21, LOW);
digitalWrite(IN_22, HIGH);
analogWrite(ENA_m2, speedCar);

digitalWrite(IN_23, HIGH);
digitalWrite(IN_24, LOW);
analogWrite(ENB_m2, speedCar);

void goAheadLeft(){

digitalWrite(IN_11, HIGH);
digitalWrite(IN_12, LOW);
analogWrite(ENA_m1, speedCar);

digitalWrite(IN_13, LOW);
digitalWrite(IN_14, HIGH);
analogWrite(ENB_m1, speedCar);

digitalWrite(IN_21, LOW);
digitalWrite(IN_22, HIGH);
analogWrite(ENA_m2, speedCar/speed_Coeff);

digitalWrite(IN_23, HIGH);
digitalWrite(IN_24, LOW);
analogWrite(ENB_m2, speedCar/speed_Coeff);

void goBackRight(){

digitalWrite(IN_11, LOW);
digitalWrite(IN_12, HIGH);
analogWrite(ENA_m1, speedCar/speed_Coeff);

digitalWrite(IN_13, HIGH);
digitalWrite(IN_14, LOW);
analogWrite(ENB_m1, speedCar/speed_Coeff);

digitalWrite(IN_21, HIGH);
digitalWrite(IN_22, LOW);
analogWrite(ENA_m2, speedCar);

digitalWrite(IN_23, LOW);
digitalWrite(IN_24, HIGH);
analogWrite(ENB_m2, speedCar);

void goBackLeft(){

digitalWrite(IN_11, LOW);
digitalWrite(IN_12, HIGH);
analogWrite(ENA_m1, speedCar);
digitalWrite(IN_13, HIGH);
digitalWrite(IN_14, LOW);
analogWrite(ENB_m1, speedCar);

digitalWrite(IN_21, HIGH);
digitalWrite(IN_22, LOW);
analogWrite(ENA_m2, speedCar/speed_Coeff);

digitalWrite(IN_23, LOW);
digitalWrite(IN_24, HIGH);
analogWrite(ENB_m2, speedCar/speed_Coeff);

void stopRobot(){

digitalWrite(IN_11, LOW);
digitalWrite(IN_12, LOW);
analogWrite(ENA_m1, speedCar);

digitalWrite(IN_13, LOW);
digitalWrite(IN_14, LOW);
analogWrite(ENB_m1, speedCar);

digitalWrite(IN_21, LOW);
digitalWrite(IN_22, LOW);
analogWrite(ENA_m2, speedCar);

digitalWrite(IN_23, LOW);
digitalWrite(IN_24, LOW);
analogWrite(ENB_m2, speedCar);

void loop(){

if (Serial.available() > 0) {
command = Serial.read();
stopRobot(); //Initialize with motors stopped.
if (lightFront) {digitalWrite(light_FR, HIGH); digitalWrite(light_FL, HIGH);}
if (!lightFront) {digitalWrite(light_FR, LOW); digitalWrite(light_FL, LOW);}
if (lightBack) {digitalWrite(light_BR, HIGH); digitalWrite(light_BL, HIGH);}
if (!lightBack) {digitalWrite(light_BR, LOW); digitalWrite(light_BL, LOW);}
if (horn) {digitalWrite(horn_Buzz, HIGH);}
if (!horn) {digitalWrite(horn_Buzz, LOW);}

switch (command) {
case 'F':goAhead();break;
case 'B':goBack();break;
case 'L':goLeft();break;
case 'R':goRight();break;
case 'I':goAheadRight();break;
case 'G':goAheadLeft();break;
case 'J':goBackRight();break;
case 'H':goBackLeft();break;
case '0':speedCar = 100;break;
case '1':speedCar = 115;break;
case '2':speedCar = 130;break;
case '3':speedCar = 145;break;
case '4':speedCar = 160;break;
case '5':speedCar = 175;break;
case '6':speedCar = 190;break;
case '7':speedCar = 205;break;
case '8':speedCar = 220;break;
case '9':speedCar = 235;break;
case 'q':speedCar = 255;break;
case 'W':lightFront = true;break;
case 'w':lightFront = false;break;
case 'U':lightBack = true;break;
case 'u':lightBack = false;break;
case 'V':horn = true;break;
case 'v':horn = false;break;

}
}
}
113) Arduino Control Servo Power with a Transistor projet

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Darlington High Power Transistor


× 1

Servos (Tower Pro MG996R)


× 1

Jumper wires (generic)

× 1

ABOUT THIS PROJECT

I was looking for an easy way to "cut" the power to a servo when it was
not in use to conserve power and was surprised to see so few articles
and blog posts on the subject. I found some, but usually using the
wrong transistor or mechanical relays. I've found this method as the
most elegant approach and thought it worth sharing. I'm not an
electronics engineer, but from what I've read, this is the proper way to
provide high current to a device using an Arduino.
SCHEMATICS

CODE

#include <Servo.h>
Servo servo;
int powerControl = 8;
int servoPin = 10;

void setup() {
//Debug
Serial.begin(9600);

// pin 8 to base of Transistor


pinMode(powerControl, OUTPUT);
Serial.println("Transistor base set to pin " + String(powerControl, DEC));

//pin 10 to Servo signal line


pinMode(servoPin, OUTPUT);
Serial.println("Servo signal set to pin " + String(servoPin, DEC));

void loop() {

/*--------------------------------
ATTACH servo signal to pin 10, turn
ON servo power and MOVE (0 to 180)
--------------------------------*/

// turn on the pwm signal to the servo


servo.attach(servoPin);
Serial.println("Servo attached to " + String(servoPin, DEC));

// turn on servo power


digitalWrite(powerControl, HIGH);
Serial.println("Servo Power is ON");

//Sweep the servo 0 to 180


for (int servoPosition = 0; servoPosition < 181; servoPosition += 5) {
servo.write(servoPosition);
Serial.println("Position: " + String(servoPosition, DEC));
delay(15);
}

//Wait for servo to execute last position


delay(500);
/*--------------------------------
Turn OFF servo, DETACH pin 10 and
WAIT for 1 second
--------------------------------*/

//turn off servo power


digitalWrite(powerControl, LOW);
Serial.println("Servo power is OFF");

//turn off the pwm signal to the servo


servo.detach();
Serial.println("Servo detached");

//wait for 1 second


delay(1000);

/*--------------------------------
ATTACH servo signal to pin 10, turn
ON servo power and MOVE (0 to 180)
--------------------------------*/

// turn on the pwm signal to the servo


servo.attach(servoPin);
Serial.println("Servo attached to " + String(servoPin, DEC));

// turn on servo power


digitalWrite(powerControl, HIGH);
Serial.println("Servo Power is ON");

//Sweep the servo 180 to 0


for (int servoPosition = 180; servoPosition >= 0; servoPosition -= 5) {
servo.write(servoPosition);
Serial.println("Position: " + String(servoPosition, DEC));
delay(15);
}

//Wait for servo to process last position


delay(500);

/*--------------------------------
Turn OFF servo, DETACH pin 10 and
WAIT for 1 second
--------------------------------*/

// turn off servo power


digitalWrite(powerControl, LOW);
Serial.println("Servo Power is OFF");

//turn off the pwm signal to the servo


servo.detach();
Serial.println("Servo detached");

//wait for 1 second


Serial.println("Waiting for 1 sec...");
delay(1000);

114) Arduino Hand Gesture Recognition Sensor projet


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Seeed PAJ7620U2 Grove -


Gesture × 1
ABOUT THIS PROJECT

Hello, and welcome, this fast tutorial is about the PAJ7620 hand
gestures sensor, it permits your hand gestures to be detected by the
Arduino board, and then you can use it to control lights, robots (cool
stuff), HMI, games… using IR LED and optical CMOS array, it can
detect up to 15 gestures.
This one costs around $2-3 only but is not efficient (as you can see in
the video) as the thermal imaging arrays that can much detect complex
gestures cost around $30-40.
The gestures that can be detected are: right, left, up, down, forward,
backward, clockwise, counter-lockwise and waving. Those are the
basic 9 then you can add right-left, left-right, up-down, down-up,
forward-backward, backward-forward. (Check the video to know the
differences).
There are two ways of detecting:
Near, which is on 5-15 cm distance with 60° angle
Far, on 15-30 cm distance with 30° angle
For this project I’m going to interface it with Arduino Uno board, and
I’ll use a LCD i²c screen to show the gesture detected, using this
method you can adapt it to whatever project you’re working on.
Parts
Uno board
LCD i²c (Optional)

PAJ7620

Test
The tests are straight forward, just plug and start moving your hands.
Direct test with the Serial Monitor

Using the LCD


Overall the module performances are not bad for $2, sometimes it can
be tricky when detecting the Forward gesture, you can check the code
to actually find that it can be confused with other gestures, you can
always modify the detection speed for all and for the forward and
backward alone:

Also, make sure the module is on a flat surface, otherwise the


clockwise and anti-clockwise gestures won’t be detected. Make sure
you have enough space for you hand to move.
SCHEMATICS
CODE

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include "paj7620.h"

#define I2C_ADDR 0x27 //I2C adress, you should use the code to scan the adress first
(0x27) here
#define BACKLIGHT_PIN 3 // Declaring LCD Pins
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

#define GES_REACTION_TIME 500


#define GES_ENTRY_TIME 800
#define GES_QUIT_TIME 1000

LiquidCrystal_I2C
lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

void setup() {
paj7620Init();

lcd.begin (16,2);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH); //Lighting backlight

void printing(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Gesture Sensor");
lcd.setCursor(0,1);
}

void loop() {

uint8_t data = 0, data1 = 0, error;

error = paj7620ReadReg(0x43, 1, &data); // Read Bank_0_Reg_0x43/0x44 for gesture


result.
if (!error)
{

switch (data) // When different gestures be detected, the variable 'data' will be set
to different values by paj7620ReadReg(0x43, 1, &data).
{
case GES_RIGHT_FLAG:
delay(GES_ENTRY_TIME);
paj7620ReadReg(0x43, 1, &data);
if(data == GES_FORWARD_FLAG)
{
printing();
lcd.print("Forward");
delay(GES_QUIT_TIME);
}
else if(data == GES_BACKWARD_FLAG)
{
printing();
lcd.print("Backward");
delay(GES_QUIT_TIME);
}
else
{
printing();
lcd.print("Right");
}
break;
case GES_LEFT_FLAG:
delay(GES_ENTRY_TIME);
paj7620ReadReg(0x43, 1, &data);
if(data == GES_FORWARD_FLAG)
{
printing();
lcd.print("Forward");
delay(GES_QUIT_TIME);
}
else if(data == GES_BACKWARD_FLAG)
{
printing();
lcd.print("Backward");
delay(GES_QUIT_TIME);
}
else
{
printing();
lcd.print("Left");
}
break;
case GES_UP_FLAG:
delay(GES_ENTRY_TIME);
paj7620ReadReg(0x43, 1, &data);
if(data == GES_FORWARD_FLAG)
{
printing();
lcd.print("Forward");
delay(GES_QUIT_TIME);
}
else if(data == GES_BACKWARD_FLAG)
{
printing();
lcd.print("Backward");
delay(GES_QUIT_TIME);
}
else
{
printing();
lcd.print("Up");
}
break;
case GES_DOWN_FLAG:
delay(GES_ENTRY_TIME);
paj7620ReadReg(0x43, 1, &data);
if(data == GES_FORWARD_FLAG)
{
printing();
lcd.print("Forward");
delay(GES_QUIT_TIME);
}
else if(data == GES_BACKWARD_FLAG)
{
printing();
lcd.print("Backward");
delay(GES_QUIT_TIME);
}
else
{
printing();
lcd.print("Down");
}
break;
case GES_FORWARD_FLAG:
printing();
lcd.print("Forward");
delay(GES_QUIT_TIME);
break;
case GES_BACKWARD_FLAG:
printing();
lcd.print("Backward");
delay(GES_QUIT_TIME);
break;
case GES_CLOCKWISE_FLAG:
printing();
lcd.print("Clockwise");
break;
case GES_COUNT_CLOCKWISE_FLAG:
printing();
lcd.print("anti-clockwise");
break;
default:
paj7620ReadReg(0x44, 1, &data1);
if (data1 == GES_WAVE_FLAG)
{
printing();
lcd.print("wave");
}
break;
}
}

delay(100);

}
115) Arduino Servo Motor Control with Remote projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

SG90 Micro-servo motor

× 1

IR receiver (generic)
× 1

JustBoom IR Remote

× 1

Jumper wires (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

With this simple Arduino project you can control servo using a remote
control. All you need is an Arduino Uno board (or similar), a servo
motor (doesn't have to be very powerful), a TV remote, IR receiver
(TS0P1738) and a small piece of cardboard.

Let's get started!


Installing the IR Library:
The very first thing that we need to do associating with arduino is to
download the IR library.
Download IR library from below link and install
it: https://github.com/z3t0/Arduino-IRremote

Decoding IR Signals:
First you need to connect the parts as per the given circuit diagram:

You can checkout Pin out of TSOP1738 below:

Use following code to decode IR remote:


/*The IR sensor's pins are attached to Arduino as so:Pin 1 to Vout (pin
11 on Arduino)Pin 2 to GNDPin 3 to Vcc (+5v from
Arduino)*/#include <IRremote.h>int IRpin = 11;IRrecv
irrecv(IRpin);decode_results results;void setup(){Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver}void loop() { if
(irrecv.decode(&results)) { Serial.println(results.value, DEC); //
Print the Serial 'results.value' irrecv.resume(); // Receive the next
value }}

Open Arduino IDE and Upload code


Open Serial Monitor
Aim your remote at the sensor and press each button
You can see different numbers for each button
Consider any two buttons, and note down decoded values.In my case I
have chosen Power button and Mode button.
I got the following values:
Power button=33441975
Mode button =33446055
We will be using this two values to control rotation of servo motor.you
need to add this two values in the program which is given on next step:
Let's set-up the final hardware!
The Final Circuit!

Connect the servo's signal pin to pin#9 on the arduino


connect the servo's VCC and GND pins to 5V VCC and GND on the
arduino
The servo will be glued to one end of the plastic bottle, and rotate a
piece of cardboard small enough to close the opening of the bottle so
that the food is blocked.
If all the hardware set-up is connected properly, you can simply
compile and upload the following sketch to the board.

SCHEMATICS
CODE

#include <IRremote.h>
#include <Servo.h>
int IRpin = 11; // pin for the IR sensor
IRrecv irrecv(IRpin);
decode_results results;
Servo myservo;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
if (irrecv.decode(&results))
{
irrecv.resume(); // Receive the next value
}
if (results.value == 33441975) // change according to your IR remote button number
{
myservo.write(0);
delay(15);
}
if (results.value == 33446055) // change according to your IR remote button number
{
myservo.write(30);
delay(15);
}

}
116) Arduino Simon Says projet

COMPONENTS AND SUPPLIES

Arduino Nano R3
Other Arduino boards work just × 1
fine.

LED (generic)
Four 5mm LEDs. Preferably Red,
× 1
Blue, Yellow and Green.

Resistor 330 ohm


Resistors between 150 ohm and
× 1
330 ohm should work fine.

Resistor 1k ohm
Pulldown resistors for the buttons.
× 1

Breadboard (generic)

× 1

Buzzer
OPTIONAL: If you want sound.
× 1

Jumper wires (generic)


For wiring the things together.
× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

I will provide you the code and the wiring instructions, if you have all
the components ready it shouldn't take more than 30 minutes. This is
also the first time I'm writing a guide on Hackster, if you think I'm
wrong on some aspects or if you think it can be improved please leave
feedback in the comment section.
Wiring Instructions
I use 1k pulldown resistors for the buttons, 100 ohm resistor for the
Piezzo Buzzer and 330 ohm resistors for the LEDs. Start by putting on
the buttons and the LEDs first, then add the resistors and finally add
the jumper wires.
The following pins on the Arduino are used:
/* Pin settings */
static const int Game::MICROPHONE_PIN = 12;
static const int Game::BLUE_PIN = 11;
static const int Game::RED_PIN = 10;
static const int Game::GREEN_PIN = 9;
static const int Game::YELLOW_PIN = 8;
static const int Game::BLUE_BUTTON_PIN = 7;
static const int Game::RED_BUTTON_PIN = 6;
static const int Game::GREEN_BUTTON_PIN = 5;
static const int Game::YELLOW_BUTTON_PIN = 4;
You can then customize the tone frequencies or the level seed. In the
setup function:
randomSeed(0);
If you replace 0 with 1 then all the levels will be randomized, if you
change it back to 0 then the game will play like before the change. In
the video I also added a reset button which connects the Arduino's RST
pin to GND.
Code
The code is written in C++ and it uses classes, if you see this for the
first time, don't be afraid, they're like containers for functions and
variables. If you want to learn more search for a C++ tutorial on
classes.

SCHEMATICS
CODE
/*
* To add a reset button connect: reset -> button <- pulldown resistor ground.
* The buttons have 1k pulldown resitors.
* The leds have a 220 ohm resistor.
*
* Will use the following numbers for colors, pins and notes
* 0 - Yellow
* 1 - Green
* 2 - Red
* 3 - Blue
*
*/

/*
* The game class, handles everything.
*/
class Game {
private:
int debounce(int last, int buttonPin);
void playNote(int note, int noteSpeed) const;
void flashLed(int led, int flashSpeed) const;
public:
static const int RED_PIN;
static const int BLUE_PIN;
static const int GREEN_PIN;
static const int YELLOW_PIN;
static const int MICROPHONE_PIN;
static const int RED_BUTTON_PIN;
static const int BLUE_BUTTON_PIN;
static const int GREEN_BUTTON_PIN;
static const int YELLOW_BUTTON_PIN;
static const int RED_TONE;
static const int BLUE_TONE;
static const int GREEN_TONE;
static const int YELLOW_TONE;
static const int GAMEOVER_TONE;
int gameLevel[200];
int gameSpeed;
int lastButtonValue;
int currentLevel;
int gameIsOver;
double gameDifficulty;
enum color { YELLOW, GREEN, RED, BLUE };
public:
Game();
Game(int);
void playLevel();
int userInput();
int gameOver();
int getNote(int note) const;
int pinToColorCode(int);
int colorCodeToPin(int);
int readButton(int buttonPin);
};

/* Pin settings */
static const int Game::MICROPHONE_PIN = 12;
static const int Game::BLUE_PIN = 11;
static const int Game::RED_PIN = 10;
static const int Game::GREEN_PIN = 9;
static const int Game::YELLOW_PIN = 8;
static const int Game::BLUE_BUTTON_PIN = 7;
static const int Game::RED_BUTTON_PIN = 6;
static const int Game::GREEN_BUTTON_PIN = 5;
static const int Game::YELLOW_BUTTON_PIN = 4;
/* Tone frequencies */
static const int Game::RED_TONE = 200;
static const int Game::BLUE_TONE = 400;
static const int Game::YELLOW_TONE = 600;
static const int Game::GREEN_TONE = 800;
static const int Game::GAMEOVER_TONE = 1000;

// Construct and initialize the Game object.


Game::Game(int difficulty) : gameSpeed(1000), lastButtonValue(-1), currentLevel(0),
gameDifficulty(difficulty), gameIsOver(0) {
Serial.print("Constructing game object with difficulty: ");
Serial.println(difficulty);
pinMode(Game::MICROPHONE_PIN, OUTPUT);
pinMode(Game::BLUE_PIN, OUTPUT);
pinMode(Game::RED_PIN, OUTPUT);
pinMode(Game::GREEN_PIN, OUTPUT);
pinMode(Game::YELLOW_PIN, OUTPUT);
}

Game::Game() : gameSpeed(1000), lastButtonValue(-1), currentLevel(0),


gameDifficulty(10), gameIsOver(0) {
Serial.println("Constructing game object");
pinMode(Game::MICROPHONE_PIN, OUTPUT);
pinMode(Game::BLUE_PIN, OUTPUT);
pinMode(Game::RED_PIN, OUTPUT);
pinMode(Game::GREEN_PIN, OUTPUT);
pinMode(Game::YELLOW_PIN, OUTPUT);
}

/*
* Makes sure the button is pressed only once.
*/
int Game::debounce(int last, int buttonPin) {
int current = digitalRead(buttonPin);
if (last != current)
{
delay(5);
current = digitalRead(buttonPin);
}
return current;
}

/*
* Plays a note.
* Receives the button number and plays the corresponding note.
*/
void Game::playNote(int note, int noteSpeed) const {
Serial.print("playNote: Playing note: ");
Serial.print(note);
Serial.print(" with speed: ");
Serial.println(noteSpeed);

note = Game::getNote(note);

tone(Game::MICROPHONE_PIN, note, noteSpeed);


}

/*
* Returns the corresponding color code based on pin.
*/
int Game::colorCodeToPin(int value) {
int ret_val = -1;

switch(value) {
case RED:
ret_val = Game::RED_PIN;
break;
case GREEN:
ret_val = Game::GREEN_PIN;
break;
case BLUE:
ret_val = Game::BLUE_PIN;
break;
case YELLOW:
ret_val = Game::YELLOW_PIN;
break;
default:
Serial.println("colorCodeToPin: Invalid value!");
delay(1000);
exit(0);
}

return ret_val;
}
/*
* Converts the button pin to a color code.
*/
int Game::pinToColorCode(int value) {
int ret_val = -1;
switch(value) {
case Game::RED_BUTTON_PIN:
ret_val = RED;
break;
case Game::GREEN_BUTTON_PIN:
ret_val = GREEN;
break;
case Game::BLUE_BUTTON_PIN:
ret_val = BLUE;
break;
case Game::YELLOW_BUTTON_PIN:
ret_val = YELLOW;
break;
default:
Serial.println("pinToColorCode: Invalid value!");
delay(1000);
exit(0);
}

return ret_val;
}

/*
* The the corresponding note based on the color code it receives.
*/
int Game::getNote(int note) const {
int return_value = -1;
switch(note) {
case YELLOW:
return_value = Game::YELLOW_TONE;
break;
case GREEN:
return_value = Game::GREEN_TONE;
break;
case RED:
return_value = Game::RED_TONE;
break;
case BLUE:
return_value = Game::BLUE_TONE;
break;
case 4:
return_value = Game::GAMEOVER_TONE;
break;
default:
Serial.println("playNote: Error! Invalid note!");
delay(1000);
exit(0);
}
return return_value;
}

/*
* Flashes a led. Receives the led code and sets it to the corresponding pin.
*/
void Game::flashLed(int led, int flashSpeed) const {
Serial.print("flashLed: Flashing LED: ");
Serial.print(led);
Serial.print(" with speed: ");
Serial.println(flashSpeed);

led = Game::colorCodeToPin(led);

digitalWrite(led, HIGH);
delay(flashSpeed);
digitalWrite(led, LOW);
}

/*
* Plays the next level.
*/
void Game::playLevel() {
Serial.print("playLevel: Playing on level: ");
Serial.println(Game::currentLevel);
Game::gameLevel[Game::currentLevel] = random(0, 4); // Create a random move every
time. 0 to 4 exclusive.
++Game::currentLevel;
int nextDificulty = Game::gameDifficulty * Game::currentLevel;
if (Game::gameSpeed - nextDificulty >= 10) {
Game::gameSpeed -= nextDificulty; // decrease the speed;
}

// Play all the moves


for (int i = 0; i < Game::currentLevel; ++i) {
Game::playNote(Game::gameLevel[i], Game::gameSpeed);
Game::flashLed(Game::gameLevel[i], Game::gameSpeed);
}
}

/*
* Reads the button value and returns the following codes:
* 0 - Yellow 1 - Green 2 - Red 3 - Blue
*/
int Game::readButton(int buttonPin) {
int currentButtonValue = Game::debounce(Game::lastButtonValue, buttonPin);
int return_value = -1;
if (lastButtonValue == LOW && currentButtonValue > LOW) {
return_value = Game::pinToColorCode(buttonPin);
}
Game::lastButtonValue = currentButtonValue;
if (return_value >= 0) {
Serial.print("readButton: Received signal from button number: ");
Serial.println(return_value);
}
return return_value;
}

int Game::gameOver() {
Serial.println("game_is_over: Checking if game is over!");
if (Game::gameIsOver) {
Serial.println("game_is_over: Game is over!");
}
return Game::gameIsOver;
}

/*
* Gets the user button presses and checks them to see if they're good.
*/
int Game::userInput() {
for (int i = 0; i < Game::currentLevel; ++i) {
Serial.println("userInput: User is pressing.");
int buttonPressed = -1;
while(true) {
buttonPressed = readButton(Game::RED_BUTTON_PIN);
if (buttonPressed != -1) { break; }
buttonPressed = readButton(Game::GREEN_BUTTON_PIN);
if (buttonPressed != -1) { break; }
buttonPressed = readButton(Game::YELLOW_BUTTON_PIN);
if (buttonPressed != -1) { break; }
buttonPressed = readButton(Game::BLUE_BUTTON_PIN);
if (buttonPressed != -1) { break; }
}
if (buttonPressed != gameLevel[i]) {
Game::playNote(4, 100); // game over note, and game over note speed.
Game::flashLed(buttonPressed, 1000);
return 0;
}
Game::playNote(buttonPressed, Game::gameSpeed);
Game::flashLed(buttonPressed, Game::gameSpeed);
}
delay(500);
return 1;
}

Game g(50); // Constructs the game object.


void setup() {
Serial.begin(9600);
randomSeed(0);
}

void loop() {
if (g.gameOver()) {
delay(1000); // Wait for serial to finish printing.
/*
On Arduino exit(0) disables the interrupts
and goes in an infinite loop.
On your PC exit(0) closes the program and
tries to clean up resources.
*/
exit(0);
}
g.playLevel();
if (g.userInput() == 0) {
g.gameIsOver = 1;
}
}
117) Arduino Adjusting Clock on 128X64 Monochrome Display projet
COMPONENTS AND SUPPLIES
Maxim Integrated DS3231MPMB1
Peripheral Module
× 1

LCD 12864 ST7920


× 1

Breadboard (generic)
× 1

Jumper wires (generic)

× 1

Rotary Encoder with Push-Button

× 1

Arduino Nano R3

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Using a 128×64 monochrome display with an ST7920, I made an


adjusting RTC clock based on an Arduino board.
Part for adjusting clock is from Doz’ Blog.
I use u8glib library and my set for ST7920 display is

If button from roary encoder is short pushed, you can see:

And if long push (more 3-4 seconds), clock enter in adjust mode, first
for year.
After you push again button, you can adjust mounth (rotate left for
decrease value and rotate right for encrease the value).

After that, you can adjust day of month.


Next is to adjust the hour.

Then minutes.

SCHEMATICS
CODE
#include <Wire.h>
#include "RTClib.h"
#include <Encoder.h> // from http://www.pjrc.com/teensy/td_libs_Encoder.html
Encoder knob(3, 2); //encoder connected to pins 2 and 3 (and ground)

#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] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
//char daysOfTheWeek[7][12] = {"Duminica", "Luni", "Marti", "Miercuri", "Joi", "Vineri",
"Sambata"};

#include "U8glib.h"
// setup u8g object, please remove comment from one of the following constructor calls
// IMPORTANT NOTE: The complete list of supported devices is here:
http://code.google.com/p/u8glib/wiki/device
// U8GLIB_ST7920_128X64_1X u8g(13, 11, 10); // SPI Com: SCK = en = 13, MOSI = rw
= 11, CS = di = 10
// se orginal code for your LCD!!!!!!
//U8GLIB_KS0108_128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 13, 2, 3, A5, 12); // 8Bit Com:
D0..D7: 8,9,10,11,4,5,6,7 en=18, cs1=14, cs2=15,di=17,rw=16
U8GLIB_ST7920_128X64_1X u8g(7, 6, 5 ,8); //Enable, RW, RS, RESET

int X = 0;
int Y = 0;
int I = 0;
int X2 = 0;
int Y2 = 0;
int X3 = 0;
int Y3 = 0;
int Timer = 0;
int Minutt = 0;
int Sekund = 0;
float Vinkel = 0;
int an = 0;
int luna = 0;
int zi = 0;
int zis = 0;

int ScreenWith = 128;


int ScreenWithC = 64;
int ScreenHeight = 64;
int ScreenHeightC = 32;
int yArray[128];
int deics = ScreenWith/4;
int deigrec = 14;
int deics2 = 0;
int de = 10;

//the variables provide the holding values for the set clock routine
int setyeartemp;
int setmonthtemp;
int setdaytemp;
int setoretemp;
int setzitemp;
int setminstemp;
int setsecs = 0;
int maxday; // maximum number of days in the given month
int TimeMins; // number of seconds since midnight
int TimerMode = 2; //mode 0=Off 1=On 2=Auto
int TimeOut = 10;
int TimeOutCounter;

// These variables are for the push button routine


int buttonstate = 0; //flag to see if the button has been pressed, used internal on the
subroutine only
int pushlengthset = 1500; // value for a long push in mS
int pushlength = pushlengthset; // set default pushlength
int pushstart = 0;// sets default push value for the button going low
int pushstop = 0;// sets the default value for when the button goes back high

int knobval; // value for the rotation of the knob


boolean buttonflag = false; // default value for the button flag
#define buton 4
//char s[3] = "";

#include <stdlib.h>
char tmp_string[8];

void draw(void) {
// graphic commands to redraw the complete screen should be placed here
// u8g.setFont(u8g_font_6x10);
//u8g.setFont(u8g_font_osb21);
TegnKlokkeBg();
DateTime now = rtc.now();
TegnViser(Timer-1, 12.0, 15); // Omdreinig, Omdreiningstall / omdreining, radius
TegnViser(Minutt-5, 60.0, 24); // Omdreinig, Omdreiningstall / omdreining, radius
// TegnViser(Sekund, 60-deics, 27); // Omdreinig, Omdreiningstall / omdreining, radius
TegnViser(Sekund-6, 60.0, 27);
// TegnViser(Sekund, 60.0, 27);

u8g.setFont(u8g_font_6x10);
u8g.setPrintPos(2*deics + deics2, 63);
if (zi < 10) u8g.print("0");
u8g.print(zi);
u8g.print("/");
if (luna < 10) u8g.print("0");
u8g.print(luna);
u8g.print("/");
//u8g.print(an-2000);
u8g.print(an);

//u8g.setPrintPos(2*deics + deics2, 50);


//u8g.print(daysOfTheWeek[zis]);

u8g.setPrintPos(2*deics + deics2+de, 28);


//u8g.setFont(u8g_font_fur17);
//u8g.setFont(u8g_font_10x20);
u8g.setFont(u8g_font_freedoomr25n);
if (Timer < 10) u8g.print(" ");
u8g.print(Timer);
if (Sekund%2 != 1)
u8g.print(":");

u8g.setPrintPos(2*deics + deics2+de, 56);


if (Minutt < 10) u8g.print("0");
u8g.print(Minutt);
u8g.setFont(u8g_font_6x10);
}

void TegnViser(float Omdreining, float forhold, int Radius) {


Vinkel = Omdreining * 2.0 * 3.1415 / forhold - 1,5707; // 12 timer blir til 2Pi
X2 = ScreenWithC -deics + Radius * cos(Vinkel);
Y2 = ScreenHeightC + Radius * sin(Vinkel);
u8g.drawLine(ScreenWithC-deics, ScreenHeightC, X2, Y2);
}

void TegnKlokkeBg() { // draw clock background


//u8g.drawCircle(ScreenWithC, ScreenHeightC, 30);
u8g.drawCircle(ScreenWithC-deics, ScreenHeightC, 1);

// u8g.setFont(u8g_font_unifont);
// u8g.setFontPosTop();
u8g.drawStr(55-deics, 4+deigrec, "12");
u8g.drawStr(83-deics, 25+deigrec, "3");
u8g.drawStr(60-deics, 45+deigrec, "6");
u8g.drawStr(39-deics, 25+deigrec, "9");

for(int TimeStrek = 0; TimeStrek<12; TimeStrek++) { // draw time lines


Vinkel = TimeStrek / 12.0 * 2 * 3.1415;
X2 = ScreenWithC-deics + 30 * cos(Vinkel);
Y2 = ScreenHeightC + 30 * sin(Vinkel);
X3 = ScreenWithC-deics + 28 * cos(Vinkel);
Y3 = ScreenHeightC + 28 * sin(Vinkel);
u8g.drawLine(X2, Y2, X3, Y3);
}

void setup(void) {

// flip screen, if required


// u8g.setRot180();

// set SPI backup if required


//u8g.setHardwareBackup(u8g_backup_avr_spi);
/*
// assign default color value
if ( u8g.getMode() == U8G_MODE_R3G3B2 )
u8g.setColorIndex(255); // white
else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )
u8g.setColorIndex(3); // max intensity
else if ( u8g.getMode() == U8G_MODE_BW )
u8g.setColorIndex(1); // pixel on
*/
// u8g.setFont(u8g_font_osb21);
u8g.setFont(u8g_font_6x10);

#ifndef ESP8266
while (!Serial); // for Leonardo/Micro/Zero
#endif

Serial.begin(9600);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}

if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// 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));
}
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

pinMode(buton,INPUT);//push button on encoder connected to A0 (and GND)


digitalWrite(buton,HIGH); //Pull button high
}

void loop(void) {
//u8g.setFont(u8g_font_unifont);
u8g.setFont(u8g_font_6x10);
DateTime now = rtc.now();
Timer = now.hour(), DEC;
Minutt = now.minute(), DEC;
Sekund = now.second(), DEC;
Serial.print(Timer);
Serial.print(':');
Serial.print(Minutt);
Serial.print(':');
Serial.print(Sekund);
Serial.print(" - ");
an = now.year(), DEC;
Serial.print(an);
Serial.print('/');
luna = now.month(), DEC;
Serial.print(luna);
Serial.print('/');
zi = now.day(), DEC;
Serial.print(zi);
Serial.print(" (");
zis = now.dayOfTheWeek();
Serial.print(daysOfTheWeek[zis]);
Serial.println(") ");

// picture loop
u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
// rebuild the picture after some delay
delay(100);

pushlength = pushlengthset;
pushlength = getpushlength();
delay (10);

if (pushlength < pushlengthset)


{
//ShortPush ();
Serial.println("short push");
// picture loop
u8g.firstPage();
do {
draw1();
} while( u8g.nextPage() );
// rebuild the picture after some delay
delay(1000);
}
//This runs the setclock routine if the knob is pushed for a long time
if (pushlength > pushlengthset) {
// lcd.clear();
Serial.println("long push");
DateTime now = rtc.now();
setyeartemp=now.year(),DEC;
setmonthtemp=now.month(),DEC;
setdaytemp=now.day(),DEC;
setoretemp=now.hour(),DEC;
setminstemp=now.minute(),DEC;
// setzitemp = now.dayOfTheWeek();
setclock();
pushlength = pushlengthset;
};
//}

} // end main loop

// subroutine to return the length of the button push.


int getpushlength()
{
buttonstate = digitalRead(buton);
if(buttonstate == LOW && buttonflag==false) {
pushstart = millis();
buttonflag = true;
};
if (buttonstate == HIGH && buttonflag==true) {
pushstop = millis ();
pushlength = pushstop - pushstart;
buttonflag = false;
};
Serial.println("_");
return pushlength;
}

void draw1(void) {
// graphic commands to redraw the complete screen should be placed here
//u8g.setFont(u8g_font_unifont);
//u8g.setFont(u8g_font_osb21);
u8g.drawStr( 10, 32, "Thx to niq_ro!");
}
//sets the clock
void setclock (){
// u8g.setFont(u8g_font_unifont);
setyear ();
setmonth ();
setday ();
// setzi();
setore ();
setmins ();
rtc.adjust(DateTime(setyeartemp,setmonthtemp,setdaytemp,setoretemp,setminstemp,setsecs));
delay (1000);
}

// The following subroutines set the individual clock parameters


int setyear () {
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
return setyeartemp;
}
knob.write(0);
delay (50);
knobval=knob.read();
if (knobval < -1) { //bit of software de-bounce
knobval = -1;
delay (50);
}
if (knobval > 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-i-
print-variable-u8glib
itoa(setyeartemp, tmp_string, 10); // https://www.avrfreaks.net/forum/how-do-i-print-
variable-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-clock-
modules-with-arduino/
118) Arduino Alarm Clock projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1

Buzzer

× 1

Thermistor
× 1

DS3231 RTC Module


× 1

Jumper wires (generic)

× 1

Potentiometer (10K)
× 1
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 <DS3231.h> //Library for RTC
Make sure you use this same library otherwise aspects of the code will
cause an error!
--------------------------------------------------------------------------------
#include <Wire.h> //Allows comunication with TWI (Two Wire
Interface)
#include <LiquidCrystal.h> //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 <DS3231.h> //Library for RTC

#include <Wire.h> //Allows comunication with TWI (Two Wire


Interface)

#include <LiquidCrystal.h> //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); // Set Day-of-Week to SUNDAY

//rtc.setTime(01, 33, 00); // 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

× 1

SparkFun Soil Moisture Sensor


(with Screw Terminals)
× 1
LED (generic)

× 1

Buzzer

× 1

Servos (Tower Pro MG996R)


× 1

Resistor 221 ohm

× 2

Jumper wires (generic)

× 1

AA Batteries

× 1
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.h>

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

10 jumper wires 200mm male


× 1

5 LDR
× 1

10 10k 1/4w resistor


× 1

Analog 180° Micro Servo


× 1

4mm cardboard
× 1
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.h>
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

Breadboard (generic)

× 1

Resistor 10k ohm

× 1
Resistor 221 ohm

× 3

General Purpose Transistor NPN

× 1

Buzzer

× 1

Tactile Button
× 1

Jumper wires (generic)

× 1

LED (generic)

× 3
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 <avr/sleep.h>
#include <avr/interrupt.h>
#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-sleep-
on-pin-state-change-code-example/
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
GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
PCMSK |= _BV(BUTTON); // Use PB3 as interrupt pin
ADCSRA &= ~_BV(ADEN); // ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above
statement
sleep_enable(); // Sets the Sleep Enable bit in the MCUCR
Register (SE BIT)
sei(); // Enable interrupts
sleep_cpu(); // sleep
cli(); // Disable interrupts
PCMSK &= ~_BV(BUTTON); // Turn off PB3 as interrupt pin
sleep_disable(); // Clear SE bit
ADCSRA |= _BV(ADEN); // ADC on
sei(); // 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); // SORT OF DEBOUNCING THE BUTTON
PRESS
}
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]; // 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 <= 0) {
MODE = BUZZ;
}
break;
case BUZZ:
// BUZZ!
digitalWrite(BUZZER, HIGH);
// FLASH!
digitalWrite(LED1, bitRead(millis() / 100, 0));
digitalWrite(LED2, bitRead(millis() / 100, 1));
digitalWrite(LED3, bitRead(millis() / 100, 2));
// SWITCH OFF WHEN THE BUTON IS PRESSED
if (button == SHORT_PRESS) {
digitalWrite(BUZZER, LOW);
clearDisplay();
sleep();
button = NO_PRESS; // FORCE THE BUTTON TO
NO_PRESS (I CAN'T REMEMBER WHY THOUGH)
}
break;
}
}

Building the Circuit

Connect the 5v to the Positive rail and the ground to the ground rail
Grab the 3 LED's and connect the anodes to a positive rail and the
cathodes to 3 separate terminal strips
Place resistors between the led's and another 3 terminal strips
Connect the LED RESISTOR pair to pins 2, 3 and 4
Place the transistor onto the breadboard
Place the buzzer between the collector and the positive rail using a jumper
wire
Connect the resistor to the base of the transistor and another terminal strip
then to pin 5 of the arduino
Connect the emitter of the transistor to the ground rail
I'm using a transistor on the buzzer because I have no idea what my
buzzer's power consumption is and I don't want to draw too much power
from one pin of the arduino.
Place the button between 2 terminal strips,
One end of the button goes to pin 6 of the Arduino and
The other end goes to the ground rail.
Usage
When I first power it up the led flashes, this indicates that the timer it is
counting down.

If I hold the button in for more than 75 milliseconds, at least one of the
LED's will be on. This means that I can choose the time I need.
If I give the button a short press he LED's change. The LED's are a 3 digit
binary number (1 through to 7 and they correspond to the times array).
I can select the time I want to countdown by giving the button a long
press. This will make the timer start counting down.
Once the countdown is complete the buzzer will ring, until you press the
button. It will then switch off.
If I tap the button when in "sleep mode" it starts counting down from the
start of last selected time.
If I want to turn it off at any time, I hold the button down for an extremely
long time and once the led's flash and I release the button, it will then turn
off.
Making it Easier to Read
Unless you can read binary the colors make using the timer 100 times
easier.
When you use a red, green and blue led covered by a diffuser, you
suddenly have 7 colours corresponding to the times in the times array.
Here I also changed the circuit to a common cathode and changed the code
accordingly.

SCHEMATICS
CODE
#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 <avr/sleep.h>
#include <avr/interrupt.h>
#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

// 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};

#if DEVICE
void sleep () { // with compliments of
https://bigdanzblog.wordpress.com/2014/08/10/attiny85-wake-from-sleep-on-pin-state-
change-code-example/
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

GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts


PCMSK |= _BV(BUTTON); // Use PB3 as interrupt pin
ADCSRA &= ~_BV(ADEN); // ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement

sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
sei(); // Enable interrupts
sleep_cpu(); // sleep

cli(); // Disable interrupts


PCMSK &= ~_BV(BUTTON); // Turn off PB3 as interrupt pin
sleep_disable(); // Clear SE bit
ADCSRA |= _BV(ADEN); // ADC on

sei(); // 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

// SELF EXPLANITORY
void beep() {
digitalWrite(BUZZER, HIGH);
delay(30);
digitalWrite(BUZZER, LOW);
}

// 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
}

// 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 <= 0) {
MODE = BUZZ;
}

break;
case BUZZ:
// BUZZ!
digitalWrite(BUZZER, HIGH);

// FLASH!
digitalWrite(LED1, bitRead(millis() / 100, 0));
digitalWrite(LED2, bitRead(millis() / 100, 1));
digitalWrite(LED3, bitRead(millis() / 100, 2));

// SWITCH OFF WHEN THE BUTON IS PRESSED


if (button == SHORT_PRESS) {
digitalWrite(BUZZER, LOW);
clearDisplay();
sleep();
button = NO_PRESS; // FORCE THE BUTTON TO NO_PRESS (I CAN'T
REMEMBER WHY THOUGH)
}
break;
}
}
122) Arduino Visual Accelerometer Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

USB-A to Micro-USB Cable


× 1

Jumper wires (generic)

× 13

Female/Female Jumper Wires

× 5

SparkFun Triple Axis


Accelerometer Breakout -
ADXL345 × 1

MAX7219 LED Driver Chip


× 1
NECESSARY TOOLS AND MACHINES
hands
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Introduction
To run this project, simply follow the wiring diagram, and then run the
code in your Arduino IDE.
I made this project as a stepping stone toward larger projects that involve
the ADLX345 accelerometer. This was made as a demonstration of how
you can utilize both the chip, and how to display its results in the Serial
monitor and physically through the LED matrix.
I decided to use the MAX7219 LED Driver to minimize the setup and the
number of wires needed. It also happens to take up only 3 pins on the
Arduino Uno which is a plus. As for how we orientate the matrix,
unfortunately for it to follow the orientation of the accelerometer, I was
not able to secure it, instead I taped it down to the board to hold it
securely.
Challenges
The biggest challenge in my opinion when building this was
understanding exactly what each address represents internally in the
accelerometer chip. I will provide a sheet sheet that I found online that
helped in setting up which addresses to READ and WRITE to.
MAX7219 Chip adapter

SCHEMATICS
CODE

#include <LedControl.h>
#include <Wire.h>

#define DEVICE (0x53) //ADXL345 device address


#define TO_READ (6) //num of bytes we are going to read (two bytes
for each axis)

byte buff[TO_READ] ; //6 bytes buffer for saving data read from the
device
char str[512]; //string buffer to transform data before sending it

int MATRIX_WIDTH = 8;
LedControl lc = LedControl(12, 11, 10, 1); // DIN, CLK, CS, NRDEV
unsigned long delaytime = 50;
int x_key = A1;
int y_key = A0;
int x_pos;
int y_pos;

// object that represents a single light location


// future update with gravity
class Grain
{
public:
int x = 0;
int y = 0;
int mass = 1;
};
Grain *g;

void setup()
{
// set up a grain object
g = new Grain();

ClearDisplay();

Wire.begin(); // join i2c bus (address optional for master)


Serial.begin(9600); // start serial for output

//Turning on the ADXL345


writeTo(DEVICE, 0x2D, 0);
writeTo(DEVICE, 0x2D, 16);
writeTo(DEVICE, 0x2D, 8);
}

void loop()
{
// The first axis-acceleration-data register
int regAddress = 0x32;
int x, y, z;

readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration


data from ADXL345

// Combine the two bytes of each direction


// Least significant bit first
x = (((int)buff[1]) << 8) | buff[0];
y = (((int)buff[3]) << 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];

// Convert the values into values that can be represented on the matrix
x = map(x, -300, 300, 0, 8);
y = map(y, -300, 300, 0, 8);
z = map(z, -300, 300, 0, 8);

//we send the x y z values as a string to the serial port


Serial.print("X: ");
Serial.print(x);
Serial.print(" Y: ");
Serial.print(y);
Serial.print(" Z: ");
Serial.print(z);
Serial.print("\n");

ClearDisplay();
// assign the grain to this location
g->x = x;
g->y = y;
lc.setLed(0, g->x, g->y, true);

//add some delay between each update


delay(10);
}
void ClearDisplay()
{
// sets up the lcd display
int devices = lc.getDeviceCount();

for (int address = 0; address < devices; address++)


{
lc.shutdown(address, false);
lc.setIntensity(address, 1);
lc.clearDisplay(address);
}
}

//Writes val to address register on device


void writeTo(int device, byte address, byte val)
{
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); //end transmission
}
//reads num bytes starting from address register on device in to buff array
void readFrom(int device, byte address, int num, byte buff[])
{
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); //sends address to read from
Wire.endTransmission(); //end transmission

Wire.beginTransmission(device); //start transmission to device


Wire.requestFrom(device, num); // request 6 bytes from device

int i = 0;
while (Wire.available()) //device may send less than requested
(abnormal)
{
buff[i] = Wire.read(); // receive a byte
i++;
}
Wire.endTransmission(); //end transmission
}
123) Arduino Cheap DIY Laser Alarm Projet
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Jumper wires (generic)

× 1

Arduino Seven Color LED


×

ABOUT THIS PROJECT


Hello peepz, I created a little laser alarm from a laser Emitter and a
Laser receiver.
I used the ky-008 laser and the laser receiver i used is called ky-008-2
on my website.
Officially it is not called ky-008-2 but any receiver will do.
This device is multi functional, i left some ideas in the code.
Check the next step for the schematic and code.
The code is just a basic code but from here you can build many cool
stuff.
So with the code you got the basics.
Step 1: Parts list.
Just wire it up like the schematic and it should work after uploading the
code.
Parts list:
Arduino Uno, (I used a copy which has 7 analog pins, a quality new
model from 2016 called RobotDyn Uno.)
1 Channel relay ky-019
Laser Sender ky-008
Laser receiver ky-008-2 (I used ky-008-2 on my website as product
code, i don't know the official code)
buzzer
7 color led ky-034
A set of Jumper wires. MM / FF / FM
A power cable and a lamp fitting + lamp connected to the relay
(optional)

SCHEMATICS
CODE

int MulticolorLed = 4; // i used the 7 color led, just for the show. You can add any led or led
module.
//you can also remove the led module to save power, if the source comes from a battery.

int Relay = 5;

int LaserEmitter = 6;

int LaserDetector = 7;

int Buzzer = 8;
// here i set up the tones, you can change them @ void loop.
int tones[] = {261, 277, 293, 311, 329, 349, 369, 392, 415, 440, 466, 493, 523 ,554};
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// You can add more tones but i added 14. Just fill in what tone you would like to use, @
void loop you see " tone(Buzzer, tones[12]); " below, digitalWrite(Buzzer, HIGH);
// here you can change the tones by filling in a number between 1 and 14

void setup()

Serial.begin (9600);

pinMode(LaserEmitter, OUTPUT);

pinMode(LaserDetector, INPUT);

pinMode(MulticolorLed, OUTPUT);

pinMode(Buzzer, OUTPUT);
digitalWrite(Buzzer, LOW);

pinMode(Relay, OUTPUT);
digitalWrite(Relay, LOW);
//+++++++++++++++++++++++++++++++++++++++++++
//Part of buzzer tones
for (int i = 0; i < Buzzer; i++)
{
}

void loop()

{
digitalWrite(LaserEmitter, HIGH);

boolean val = digitalRead(LaserDetector);

Serial.println(val); // Open the Serial Monitor to see the values

if (val == 0) // Here we set value to 0 with a if statement, because the laser sensor reads a
value of 1 or 0. Its reads value 1 when the laser is aimed at the receiver.
// so value 0 is what we set for this alarm right now. To change the alarm to a alarm that
works the other way around you simply change this value to 1.

// How would it work the other way around? well like a alarm you see in the movies that
protects a diamond.. when the diamond or any item is removed the alarm will go off.

digitalWrite(Buzzer, HIGH); // here the Buzzer is set high in order to make a sound.
tone(Buzzer, tones[6]); //here we set the tone by choosing from number 1 to 14
delay (50);
digitalWrite(Buzzer, LOW); // here we set the buzzer low and next we set noTone for the
buzzer to make a break.
noTone(Buzzer);
delay (50); //this is the delay between each buzzer beep. You can play with the sounds by
choosing from number 1 to 14
digitalWrite(Buzzer, HIGH);
tone(Buzzer, tones[9]);
delay (100);
digitalWrite(Buzzer, LOW);
noTone(Buzzer);
delay (100);
digitalWrite(Buzzer, HIGH);
tone(Buzzer, tones[14]);
delay (50);
digitalWrite(Buzzer, LOW);
noTone(Buzzer);
digitalWrite(MulticolorLed, HIGH); //Here we set the led to high, it will only flash when
the alarm is triggered
delay(250);
digitalWrite(Relay, HIGH); //here we set the relay to high, it will also only turn on when
the laser is not aimed at the laser receiver
delay(100);

}
else //here we use the else statement to turn everything off when the if statement is reading
the laser receivers value of 1

digitalWrite(Relay, LOW);// here everything turns off, so is set to low. This happens when
the laser aims at the Laser receiver.
digitalWrite(Buzzer, LOW);
noTone(Buzzer);
digitalWrite(MulticolorLed, LOW);

124) Arduino Aposture Detector Sending Bluetooth Data to a


Cordava App Projet
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

RedBear BLE Shield - RedBear


× 1

Analog Accelerometer: ADXL335


× 1

5 mm LED: Red

× 1

5 mm LED: Yellow

× 1

5 mm LED: Green

× 1

SparkFun Pushbutton switch 12mm

× 1
APPS AND ONLINE SERVICES
Arduino IDE

Apple Xcode

ABOUT THIS PROJECT


Back pain affects a large amount of people around the world, impacting
the health of the spine and leading to many health problems (negative
impacts on the quality of life, sleep disorders, respiratory problems...)
Half of back pains are caused by improper posture and could therefore
been prevented and cured by correcting the posture. The only requirement
is to actually detect a bad posture.
The focus of this project is to answer this problem: build a wearable
device that's capable of detecting bad posture and providing instant
feedback to allow the wearer to correct his posture immediately. Real-time
posture data will also be transmitted by Bluetooth on a mobile app made
with Cordova.
For this prototype, I used LEDs to give an indication of the posture but the
final product will be equiped with a vibrating module to give haptic
feedback.
Step 1: Wiring
Assemble the components by following this circuit diagram:
Step 2: Programming the Arduino board
The program sets the reference position by reading the momentary switch
when pressed by the user and does all the calulcations and values
conversion from the accelerometer.
See the code below or on codebender here
: https://codebender.cc/embed/sketch:910134 or on

Step 3: Building the mobile application


The application displays the BLE device and allows to connect to it.
Once connected, the angle is received and displayed on the app, and a line
indicating the direction of the bending is drawn at the same time.
If the position begins to be considered as bad (yellow led on), the app
indicates "warning"; If the position is considered bad (red led on), the app
indicates "wrong". You can see that behavior in the photos section below.
There is also a textbox on the app to communicate with the device in
bluetooth (useless for this project), you can see those messages on the
serial monitor.
See source code on
GitHub: https://github.com/cvirginie/CordovaPostureDetector_BLE and
follow the instructions.
Install the app on iOS:
Clone the repo https://github.com/cvirginie/CordovaPostureDetector_BLE
git clone https://github.com/cvirginie/CordovaPostureDetector_BLE.git
Then type the following commands :Navigate to the directory
cd CordovaPostureDetector_BLE/
Install the dependencies
npm install
Add the ios platform (not tested on Android)
cordova platform add ios
Build
cordova build ios
or
cordova build ios --buildFlag='-UseModernBuildSystem=0'
Open the project in XCode and deploy on your device.
The plugin used to communicate in BLE: https://github.com/don/cordova-
plugin-ble-central/
Photos:
The Posture Detector
Posture in warning (yellow led on)
Wrong posture detected (red led on)

SCHEMATICS
CODE

#include <math.h>
#include "Boards.h"
#include <SPI.h>
#include <Nordic_nRF8001.h>
#include <RBL_nRF8001.h>
#include "iShield.h"

iShield myiShield;

// momentary switch
const int buttonPin = 2;

int LED1 = 3; // Red


int LED2 = 4; // Green
int LED3 = 5; // Yellow

int buttonState = 0;
// Position set when the momentary witch is pressed
int currentBackPos;

// Value set as the "normal position" (= flat value on my accelerometer as


mine is not solder so the angle is already "forward")
int refPos = 15;

//vibration motor digital pin


//int vibePin = 9;

void setup()
{
// Init. and start BLE library.
ble_begin();
Serial.begin(9600);
ble_set_name("BLEShield");

//pinMode(buzzerPin, OUTPUT);

pinMode(LED1, OUTPUT); // Red


pinMode(LED2, OUTPUT); // Green
pinMode(LED3, OUTPUT); // Yellow

digitalWrite(LED1,LOW); // Red
digitalWrite(LED2,LOW); // Green
digitalWrite(LED3,LOW); // Yellow
pinMode(2, INPUT); // SwitchButton (to set "normal" position)
}

void loop()
{

//start reading the button state


buttonState = digitalRead(buttonPin);

// if msg is sent by bluetooth from the app, write it on the console (not
used in that project)
myiShield.readConsole();
String message = myiShield.incomingData();
Serial.println(message);

// Start reading and calculating angles


float VREF = 5.0;

// To get those values, play with your accelerometer and put the min and
max you find on every x,y,z position
int xMinVal = 265; int yMinVal = 259;int zMinVal = 281;
int xMaxVal = 398; int yMaxVal = 393;int zMaxVal = 413;

int xRead=0, yRead=0, zRead=0;

int xAng=0, yAng=0, zAng=0;


double x=0, y=0, z=0;

int ave = 10;

// read raw values


for(int i=0; i<ave ; i++)
{
xRead += analogRead(A0);
yRead += analogRead(A1);
zRead += analogRead(A2);
}

xRead = xRead/ave;
yRead = yRead/ave;
zRead = zRead/ave;

// convert to angles
xAng = map(xRead, xMinVal, xMaxVal, -90, 90);
yAng = map(yRead, yMinVal, yMaxVal, -90, 90);
zAng = map(zRead, zMinVal, zMaxVal, -90, 90);

x = 57.2957795 * (atan2(-yAng, -zAng) + 3.14159265359);


y = 57.2957795 * (atan2(-xAng, -zAng) + 3.14159265359);
z = 57.2957795 * (atan2(-yAng, -xAng) + 3.14159265359);

char xTempString[10]; // Hold The Convert Data


// convert position in string to display it
dtostrf(x,3,2,xTempString); // dtostrf( [doubleVar] , [sizeBeforePoint] ,
[sizeAfterPoint] , [WhereToStoreIt] )
String xString = String(xTempString); // cast it to string from char

// wrtie value that will be read on the mobile device


myiShield.writeConsole(xString);

currentBackPos = x;

//if the button is pressed set the value of base position to the current back
position
// this sets a "normal" state that the code will then measure a difference
from.
if (buttonState == HIGH) {

myiShield.writeConsole("button pressed");
refPos = currentBackPos;

char bkpTempString[10]; // Hold The Convert Data


dtostrf(currentBackPos,3,2,bkpTempString); // dtostrf( [doubleVar] ,
[sizeBeforePoint] , [sizeAfterPoint] , [WhereToStoreIt] )
String bkpString = String(bkpTempString); // cast it to string from char
myiShield.writeConsole("currentBackPos :");
myiShield.writeConsole(bkpString);
char bpTempString[10]; // Hold The Convert Data
dtostrf(refPos,3,2,bpTempString); // dtostrf( [doubleVar] ,
[sizeBeforePoint] , [sizeAfterPoint] , [WhereToStoreIt] )
String bpString = String(bpTempString); // cast it to string from char
myiShield.writeConsole("refPos :");
myiShield.writeConsole(bpString);
}

//if backPos is in a bad postion


if(currentBackPos > refPos + 20){
myiShield.writeConsole("wrong");

digitalWrite(LED1, HIGH);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
}
else {
if(currentBackPos > refPos + 10){
myiShield.writeConsole("warning");

digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, HIGH);
}
else{
digitalWrite(LED2, HIGH);
digitalWrite(LED1, LOW);
digitalWrite(LED3, LOW);

}
}

delay(2000);

}
125) Anti Theft Camera System using Arduino Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

Selfie stick Remote


× 1

UTSOURCE Electronic Parts

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Ever wondered about making an anti-theft device with a camera trigger
system? Or perhaps you want to make a device for your chocolate thief
little brother which would just take picture when and if he takes the
chocolate away...
To be clear, this post is all about controlling a smartphone camera via
Arduino wirelessly. I'm just providing you the process to control the
camera using Arduino. What you'll build using it is all up to you. The sky
is the limit, right? Let's hop in guys.
Step 1: Parts You'll Need
Arduino (Any development board you'd prefer)
Selfie stick remote
Any transistor // I've used BC547 NPN transistor
Step 2: Principle
Well the selfie stick remote controls phone camera using Bluetooth
technology when a button is pressed. What we will do today is to trigger
the switch anyway using Arduino.
So, we'll be using our transistor as what it was actually made to do- using
it as a switch. we'll connect the BASE pin of a transistor to Arduino. And
the emitter and collector will be attached to two points of the button of the
remote.r
The working process:
Arduino will make The base pin HIGH so the the Collector & Emitter of
Transistor will get connected and thus the button will get pressed virtually
using arduino. Got it? lets proceed.
Step 3: Open the Cover and Take Out the Remote's PCB
Carefully open the cover of the remote.
Remember which switch for which platform, there's two switches one for
Android Phones, one for IOS. You would use the button / switch as your
phones OS is.
Step 4: Build the Remote Circuit
As I've mentioned earlier connect any transistors (my case BC547 NPN)
emitter and collector to the buttons two end and the base to Arduino. Don't
forget to connect the ground pin of remote with Arduino.
NOTE: I've powered the remote with its own battery. It's powered using a
3V button cell, as Arduino has 3.3V not 3V, so I didnt take the risk. That's
why we need to common the ground pin.
Step 5: Application???
Man, you are done making this. This part is just two demonstrate how this
can be used. So I've made an infrared proximity detector and motion
camera trigger system. Remember: I've connected the output pin of
proximity sensor to analog input 'A0' so that I get a high range and guess
what? It worked for even 9 to 11 inches!
Code download: Camera Control by Arduino
Or copy from below:
/* Control any cell phone camera with Arduino Wirelessly******
By Ashraf Minhaj. Find him at [email protected]
youTube channel www.youtube.com/c/fusebatti */
/* This is a demo code with a proximity sensor on how to Trigger
the camera of your cell Phone by Arduino. You can make Ultrasound
Motion sensor or PIR sensor to work as a Motion sensing anti theft
Camera system.
* It's just an Idea , The Sky is the Limit */
int trig = 13;
void setup()
{
pinMode(trig,OUTPUT);
Serial.begin(9600); // initialize serial communication at 9600 bits per
second:
}
void loop() // the loop routine runs over and over again forever:
{
int sensorValue = analogRead(A0); // read the input on analog pin 0:
Serial.println(sensorValue); // print out the value you read:
delay(1); // delay in between reads for stability
if(sensorValue > 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);
}
}
Upload the code and see what happens.
There's also a circuit using sonar sensor HC-SR04.
SCHEMATICS
CODE
int trig = 13;
void setup()
{
pinMode(trig,OUTPUT);
Serial.begin(9600); // initialize serial communication at 9600 bits per
second:
}

void loop() // the loop routine runs over and over again forever:
{
int sensorValue = analogRead(A0); // read the input on analog pin 0:
Serial.println(sensorValue); // print out the value you read:
delay(1); // delay in between reads for stability

if(sensorValue > 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 × 1
used, but uses the same
technology.
Digilent 5V 4000mA Switching
Power Supply
Again, this wasn't the actual × 1
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 <Adafruit_NeoPixel.h>
#include <Stdint.h>

#ifdef __AVR__
#include <avr/power.h>
#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 <= 'Z')) {


currentCol = 0;
} else if (((currentChar >= '0') && (currentChar <= '9')) || (currentChar == '+') ||
(currentChar == '-')) {
currentCol = colorMode;
} else if (currentChar == '^') {
colorMode = 2;
currentCol = colorMode;
} else if (currentChar == '|') {
colorMode = 1;
currentCol = colorMode;
}

int indexValue;
if ((currentChar >= '0') && (currentChar <= '9')) indexValue = currentChar - 48; // 0-9
else if ((currentChar >= 'A') && (currentChar <= 'Z')) indexValue = currentChar - 55; //
upper case
//else if ((currentChar >= 'a') && (currentChar <= 'z')) indexValue = currentChar - 61; //
lower case , check that these are in the right place / the offset is correct, as i may have put
the array chunk back in the wrong place!!
else if ((currentChar == ' ')) indexValue = 36; // space, was 62 when lower case chars
else if ((currentChar == '^')) indexValue = 37; // up arrow, was 63 when lower case chars
else if ((currentChar == '|')) indexValue = 38; // down arrow, was 64 when lower case chars
// else if ((currentChar == '<')) indexValue = 39; // left arrow, was 65 when lower case
chars
// else if ((currentChar == '>')) indexValue = 40; // right arrow, was 66 when lower case
chars
else if ((currentChar == '-')) indexValue = 39; // dash / maintain, was 67 when lower case
chars, 41 with l/r arrows
else if ((currentChar == '+')) indexValue = 40; // plus
else if ((currentChar == '.')) indexValue = 41; // full stop

for (int x = 0; x < charWidth; x++) {


if (currentStatus == 0) currentStatus = 1;
else if (currentStatus == 1) currentStatus = 0;
setStatusIndicator(currentStatus);

nudgeColumns(displayLetters[indexValue][x], currentCol); // inputCols[i]); //


strip.Color(0,0,255));
displayUpdate(0);

delay(100);
}
nudgeColumns(0, 0); // - 1 might break things here? or make things go white due to the
lookup default being white
if (currentStatus == 0) currentStatus = 1;
else if (currentStatus == 1) currentStatus = 0;
setStatusIndicator(currentStatus);
displayUpdate(0);
delay(100); // this will be 200 as per the rest once confirmed that the double jump issue is
done!
}

if (stockStep == (stockStepQty - 1)) stockStep = 0; // is this used anymore?!


else stockStep++; // as above
}

int getIntLength(int value){


// Function created by "zed_0xff" at: https://stackoverflow.com/a/3068412/7905386
int l=!value;
while(value){ l++; value/=10; }
return l;
}

int getMappedPixel(int columnID, int rowID){


int z;

z = columnSize - columnID;
if (columnID % 2) z++;

z = z* (rowSize + 1);
if (columnID % 2) z = z - rowID - 1;
else z = z + rowID;

if (z>= 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 <= rowSize; i++) {
for (int j = 0; j <= columnSize; j++) {
setMappedColor(j, i, color);
}
}
}

void convertToBits(byte inputValue, int outputArray[]) {


//if (inputValue & 0x80) outputArray[0] = 1; // not used?
if (inputValue & 0x40) outputArray[0] = 1;
if (inputValue & 0x20) outputArray[1] = 1;
if (inputValue & 0x10) outputArray[2] = 1;
if (inputValue & 0x08) outputArray[3] = 1;
if (inputValue & 0x04) outputArray[4] = 1;
if (inputValue & 0x02) outputArray[5] = 1;
if (inputValue & 0x01) outputArray[6] = 1;
}

void displayUpdate(long backColor) {


colorAll(backColor);
for (int i = 0; i <= columnSize; i++) {
int columnData[rowSize + 1] = {0};
convertToBits(displayOutput[i], columnData);

for (int j = 0; j <= rowSize; j++) {


if (columnData[rowSize-j] == 1) setMappedColor(i, j, colorLookup(displayColors[i])); //
was displayColors[i][j] before memory save
}
}

strip.show();
stripB.show();
}

void nudgeColumns(byte newData, byte newColor) {


for (int i = 0; i < columnSize; i++) {
displayOutput[i] = displayOutput[i + 1];
for (int j = 0; j <= rowSize; j++) {
displayColors[i] = displayColors[i + 1];
}
}
displayOutput[columnSize] = newData;

if (newColor >= 0) { // created for memory save


for (int k = 0; k <= rowSize; k++) {
displayColors[columnSize] = newColor;
}
}
}

long colorLookup(int inputColor) {


long outputColor = 0;
switch (inputColor) {
case 0:
outputColor = strip.Color(255,255,255); // white
break;
case 1:
outputColor = strip.Color(255,0,0); // red
break;
case 2:
outputColor = strip.Color(0,255,0); // green
break;
case 3:
outputColor = strip.Color(0,0,255); // blue
break;
case 4:
outputColor = strip.Color(255,255,0); // yellow/amber
break;
case 5:
outputColor = strip.Color(0,255,255); // cyan
break;
case 6:
outputColor = strip.Color(255,0,255); // magenta
break;
default:
outputColor = strip.Color(255,255,255); // white
break;
}

return outputColor;
}

void setStatusIndicator(byte inputStatus) {


if (inputStatus == 0) {
digitalWrite(13, LOW);
} else {
digitalWrite(13, HIGH);
}
}

127) Arduino Horizontal POV Display Projet


COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

LED (generic)

× 7
Resistor 100 ohm

× 7

Rechargeable Battery, Lithium Ion

× 1

DC-DC Boost (Step Up) Regulator,


Adjustable
× 1

Fan Kit, 80 mm Fan

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Persistence of Vision (POV) displays are generally LED displays which
‘show’ images by displaying a section of an image at a given time, in
quick rapid succession. The human brain perceives this as display of a
continuous image. On the Maker Pro website is presented a very simple
horizontal POV display, which is composed only of Arduino and 5
LEDs. You can see the scheme in the picture below. In my case
Arduino is powered by a single lithium-ion battery to which is
connected a step up converter 3.7V to 5V. For spining the entire
assembly I use a old PC fan. In the original project, the motor turns
counterclockwise. In this particular case, the motor turns clockwise so I
had to make minimal changes in the code. I changed the order of LED1
- LED5 instead of 2, 3, 4, 5, 6, to 6, 5, 4, 3, 2 and I turned the entire
device for 180 degree. Displayed text to be stable, the correct RPM of
the motor must be adjusted, which is achieved with a variable power
source. I also added two more LED diodes with different colour, in
front of LED1 and after LED5, which gives the better visulal effect.

SCHEMATICS
CODE
int delayTime = 1;
int charBreak = 2.1;
int LED1 = 6;
int LED2 = 5;
int LED3 = 4;
int LED4 = 3;
int LED5 = 2;

void setup(){
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
pinMode(LED5, OUTPUT);
}

int a[] = {1, 6, 26, 6, 1};


int b[] = {31, 21, 21, 10, 0};
int c2[] = {14, 17, 17, 10, 0};
int d[] = {31, 17, 17, 14, 0};
int e[] = {31, 21, 21, 17, 0};
int f[] = {31, 20, 20, 16, 0};
int g[] = {14, 17, 19, 10, 0};
int h[] = {31, 4, 4, 4, 31};
int i[] = {0, 17, 31, 17, 0};
int j[] = {0, 17, 30, 16, 0};
int k[] = {31, 4, 10, 17, 0};
int l[] = {31, 1, 1, 1, 0};
int m[] = {31, 12, 3, 12, 31};
int n[] = {31, 12, 3, 31, 0};
int o[] = {14, 17, 17, 14, 0};
int p[] = {31, 20, 20, 8, 0};
int q[] = {14, 17, 19, 14, 2};
int r[] = {31, 20, 22, 9, 0};
int s[] = {8, 21, 21, 2, 0};
int t[] = {16, 16, 31, 16, 16};
int u[] = {30, 1, 1, 30, 0};
int v[] = {24, 6, 1, 6, 24};
int w[] = {28, 3, 12, 3, 28};
int x[] = {17, 10, 4, 10, 17};
int y[] = {17, 10, 4, 8, 16};
int z[] = {19, 21, 21, 25, 0};

int eos[] = {0, 1, 0, 0, 0};


int excl[] = {0, 29, 0, 0, 0};
int ques[] = {8, 19, 20, 8, 0};

void displayLine(int line){


int myline;
myline = line;
if (myline>=16) {digitalWrite(LED1, HIGH); myline-=16;} else {digitalWrite(LED1,
LOW);}
if (myline>=8) {digitalWrite(LED2, HIGH); myline-=8;} else {digitalWrite(LED2,
LOW);}
if (myline>=4) {digitalWrite(LED3, HIGH); myline-=4;} else {digitalWrite(LED3,
LOW);}
if (myline>=2) {digitalWrite(LED4, HIGH); myline-=2;} else {digitalWrite(LED4,
LOW);}
if (myline>=1) {digitalWrite(LED5, HIGH); myline-=1;} else {digitalWrite(LED5,
LOW);}
}

void displayChar(char c){


if (c == 'a'){for (int i = 0; i <5; i++){displayLine(a[i]);delay(delayTime);}displayLine(0);}
if (c == 'b'){for (int i = 0; i <5; i++){displayLine(b[i]);delay(delayTime);}displayLine(0);}
if (c == 'c2'){for (int i = 0; i <5; i++)
{displayLine(c2[i]);delay(delayTime);}displayLine(0);}
if (c == 'd'){for (int i = 0; i <5; i++){displayLine(d[i]);delay(delayTime);}displayLine(0);}
if (c == 'e'){for (int i = 0; i <5; i++){displayLine(e[i]);delay(delayTime);}displayLine(0);}
if (c == 'f'){for (int i = 0; i <5; i++){displayLine(f[i]);delay(delayTime);}displayLine(0);}
if (c == 'g'){for (int i = 0; i <5; i++){displayLine(g[i]);delay(delayTime);}displayLine(0);}
if (c == 'h'){for (int i = 0; i <5; i++){displayLine(h[i]);delay(delayTime);}displayLine(0);}
if (c == 'i'){for (int it = 0; it <5; it++)
{displayLine(i[it]);delay(delayTime);}displayLine(0);}
if (c == 'j'){for (int i = 0; i <5; i++){displayLine(j[i]);delay(delayTime);}displayLine(0);}
if (c == 'k'){for (int i = 0; i <5; i++){displayLine(k[i]);delay(delayTime);}displayLine(0);}
if (c == 'l'){for (int i = 0; i <5; i++){displayLine(l[i]);delay(delayTime);}displayLine(0);}
if (c == 'm'){for (int i = 0; i <5; i++)
{displayLine(m[i]);delay(delayTime);}displayLine(0);}
if (c == 'n'){for (int i = 0; i <5; i++){displayLine(n[i]);delay(delayTime);}displayLine(0);}
if (c == 'o'){for (int i = 0; i <5; i++){displayLine(o[i]);delay(delayTime);}displayLine(0);}
if (c == 'p'){for (int i = 0; i <5; i++){displayLine(p[i]);delay(delayTime);}displayLine(0);}
if (c == 'q'){for (int i = 0; i <5; i++){displayLine(q[i]);delay(delayTime);}displayLine(0);}
if (c == 'r'){for (int i = 0; i <5; i++){displayLine(r[i]);delay(delayTime);}displayLine(0);}
if (c == 's'){for (int i = 0; i <5; i++){displayLine(s[i]);delay(delayTime);}displayLine(0);}
if (c == 't'){for (int i = 0; i <5; i++){displayLine(t[i]);delay(delayTime);}displayLine(0);}
if (c == 'u'){for (int i = 0; i <5; i++){displayLine(u[i]);delay(delayTime);}displayLine(0);}
if (c == 'v'){for (int i = 0; i <5; i++){displayLine(v[i]);delay(delayTime);}displayLine(0);}
if (c == 'w'){for (int i = 0; i <5; i++){displayLine(w[i]);delay(delayTime);}displayLine(0);}
if (c == 'x'){for (int i = 0; i <5; i++){displayLine(x[i]);delay(delayTime);}displayLine(0);}
if (c == 'y'){for (int i = 0; i <5; i++){displayLine(y[i]);delay(delayTime);}displayLine(0);}
if (c == 'z'){for (int i = 0; i <5; i++){displayLine(z[i]);delay(delayTime);}displayLine(0);}
if (c == '!'){for (int i = 0; i <5; i++)
{displayLine(excl[i]);delay(delayTime);}displayLine(0);}
if (c == '?'){for (int i = 0; i <5; i++)
{displayLine(ques[i]);delay(delayTime);}displayLine(0);}
if (c == '.'){for (int i = 0; i <5; i++)
{displayLine(eos[i]);delay(delayTime);}displayLine(0);}
delay(charBreak);
}

void displayString(char* s){


for (int i = 0; i<=strlen(s); i++){
displayChar(s[i]);
}
}

void loop(){
displayString("hello world");
}

128) Arduino LASER Tripwire Alarm Projet


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Seeed Grove - Light Sensor

× 1
ky 008 Laser emitter
× 1

Buzzer

× 1

Push Button
× 1

4x4 keypad matrix


× 1
NECESSARY TOOLS AND MACHINES
10 Pc. Jumper Wire Kit, 5 cm Long

ABOUT THIS PROJECT


Hi, this tutorial is about "Grove Light Sensor" based project, there are two
versions of the project, and as you read it it's a LASER Tripwire Alarm,
one that you can set with a simple push button, the other one is more
secure and requires a passcode.
A tripwire is a device triggered by physical movements, you can use it to
detect people, animals, cars... when they pass through an area. This one is
based on a LASER emitter, that constantly sends beams to the light sensor,
and when someone/something passes, the sensor won't receive the beams,
and the alarm is triggered, and won't stop until you resest it (push
button/passcode).
Parts
Those are the parts used along side some jump wires
Arduino Uno board
Grove Light Sensor V1.2

Grove Light Sensor v1.2 (back)

Ky-008 LASER Emitter

3 Pins buzzer you can use 2 pin version

Push button + Resistor for Version 1

4x4 Keypad matrix you can use 3x4 one for the Version 2
Version 1
This project is based on the module, LASER module, a Buzzer, and a push
button, the idea is very simple, the LASER is constantly projecting light to
the module sensor, when a person or something passes through the light
beam, the sensor will not detect the light anymore (When the light stops,
the LDR will increase resistance, which means less current will pass, and
we’ll get a voltage drop).
Example: At indoor light the sensor will give a value of around “750”
when using the “analogRead” function while using Arduino it’s around
“3.66V” (1023 for 5V), but when you cover the sensor it will show a value
around “10-15” that stands for “40mV”. So it’s better to cover or put the
sensor in a case where only the LASER beams can reach.
Once the LASER beams are cut, the alarm will go off and will not stop
until the push button is pressed even though the module detects the
LASER again.
Below you'll find wiring and code
Version 2
The v2 is pretty much like the v1 just instead of stopping the alarm with a
simple push button, now it requires a passcode entered by the keypad to
stop it, otherwise it won’t.
The passcode is stored in an array, I chosed 4 digits code, you can make it
longer or shorter, just modify the array size, and add or remove values.
short code[4]={'1','3','6','6'};
To turn the alarm off, you should press ‘*’ on the keypad, then enter the
numbers 1, 3, 6, 6, the code will fix the buzzer in a single frequency
(disturbing) sound until you enter 4 digits, if they are correct the alarm
will stop, otherwise it will go off again.
void Getpass(){
tone(13,2000);
for(short i=0 ; i<4 ; i++)
{
char keypressed = myKeypad.waitForKey();
if (keypressed==code[i])
a++;
}
}
Every time you enter a correct digit “a” value increases, if it’s == 4, the
code is considred correct, otherwise the number will never be equal to 4.
if(a==4){
noTone(13);
a=0;
detection=false;
}

SCHEMATICS

Wiring for V1
Wiring for V2
CODE
This code works with the version 1
/* This code is for a LASER Tripwire Alarm based on a light sensor, LASER module and a
push button
* The LASER is constantly sending beams to the sensor, when someone passes the light is
not detected
* and the alarm goes off, and will not stop until you press the button

*/

#define Rec 0 //Light sensor output


#define Laser 2 //Laser module
#define Button 3 //Push button input

bool detection;

void setup() {
pinMode(Laser, OUTPUT);
digitalWrite(Laser, HIGH); //Turning on the laser
delay(2000);
}

void loop() {

short Detect = analogRead(Rec); //Constanly reading the module value


bool Button_state = digitalRead(Button); //And the button value (1-0)

if(Detect < 500) //The Max value is 760, if someone passes it goes below that (every
value lower than 700 can do the work)
detection = true; //The detection is triggered

if(detection==true)
{
tone(13,2000); //Alarm sequence will go on as long as the detection is true
delay(50); //This alarm has two sounds 2kHz nd 1Khz delayed by 50ms
tone(13,1000);
delay(50);
}

if(Button_state == HIGH) //If the button is pressed the buzzer is turned off and the
detection too
{
detection = false;
noTone(13);
}

This code works with the version 2

/* This code is for a LASER Tripwire Alarm based on a light sensor, LASER module and
keypad
* The LASER is constantly sending beams to the sensor, when someone passes the light is
not detected
* and the alarm goes off, and will not stop until you press '*' and enter the correct code
*/

#include <Keypad.h>

#define Rec 0
#define Laser 2
#define Button 3

bool detection;
short a=0;
short code[4]={'1','3','6','6'}; //pass code stored in a array you can make it longer or shorter
//by changing '4' and add/remove values

const byte numRows= 4; //Rows and columns of the keypad


const byte numCols= 4;

char keymap[numRows][numCols]= //Keypad map


{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[numRows] = {11,10,9,8}; //Keypad 8 pins


byte colPins[numCols]= {7,6,5,4};
Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows,
numCols);

void setup() {

pinMode(Laser, OUTPUT);
digitalWrite(Laser, HIGH);
delay(2000);
}

void loop() {

short Detect = analogRead(Rec); //Constantly reading the sensor value, to detect


if someone passes

if(Detect < 500)


detection = true;

if(detection==true)
{ //Alarm sequence and constantly waiting for '*' to be pressed
tone(13,1000);
delay(50);
tone(13,200);
delay(50);
char keypressed = myKeypad.getKey();
if (keypressed == '*') //if '*' is pressed go to Getpass function
Getpass();
}

if(a==4){ //if a==4 means the code is correct, the alarm is off
noTone(13);
a=0; //setting the a to 0, otherwise the alarm will turn off
automatically
detection=false;
}

void Getpass(){ //Getting passcode function


tone(13,2000); //Constant frequency sound while entring the code
for(short i=0 ; i<4 ; i++)
{

char keypressed = myKeypad.waitForKey();


if (keypressed==code[i]) //If the sequence is correct the a increases (4) means all values
are right
a++;
}
}
129) Arduino Greenhouse Projet

COMPONENTS AND SUPPLIES

5 mm LED: Red

× 1

5 mm LED: Green
× 1

Photo resistor

× 1

Resistor 10k ohm

× 3

Resistor 221 ohm


*220 ohm
× 2

PIR Motion Sensor (generic)

× 1

Buzzer

× 1

Temperature Sensor

× 1

SG90 Micro-servo motor


× 1

Arduino UNO & Genuino UNO

× 1

water level
× 1

hygrometrer
× 2

relay
× 2

lamp holder
× 1

LED Light Bulb, Frosted GLS

× 1

plug
× 1

water pump
× 1

plexiglass
× 1

zippers
× 4

rubber feet
× 4

connecting wires
× 40

Accessory, Screw

× 36
NECESSARY TOOLS AND MACHINES
welding machine

Multitool, Screwdriver

saw

Wire Stripper & Cutter, 30-10 AWG Solid &


Stranded Wires

Cable Cutter, 200mm

cutter

sander

Drill / Driver, Cordless


APPS AND ONLINE SERVICES
Tinkercad

ABOUT THIS PROJECT


This project saves time and keeps the plant healthycontinously thanks to
greenhouse automation. It is also able to communicate byboth visual and
acoustic signal with external beings capable of receiving them.
INTRODUCTION:
The purpose of this project is to build a greenhouse usingArduino. The
greenhouse deals with plants in a totally automatic way. Inparticular, it is
based on an Arduino Uno board, to which revolve aroundseveral sensors
useful to analyze the conditions necessary for properoperation. These
include the presence of the humidity and temperature sensor(TMP36), two
photo-resistance, a water level and finally an PIR HC - SR501.
Theoperation of this project is to detect a set of data using the
sensorsdescribed above and based on the value they detect, different
mechanisms willbe activated that can keep the plant healthy.
FUNCTION:
1. In this project, twophotoresistors are placed above the top surface of the
greenhouse, whichtransmit various values depending on the brightness of
the externalenvironment. Subsequently you will average the values and
according to it willturn on an internal light to feed the plants or you will
act a servo motor thatis tasked with opening the upper panel allowing the
light of the external environmentto radiate the shrubs inside the
greenhouse, saving the artificial lighting incase of brightness needed to
power them. Outside the greenhouse is placed atemperature sensor that is
able to detect the external temperature, this factorinfluences the drive of
the servo. If the detected value will be below a presetthreshold then the
servo will not act even if the external brightness is highand the lamp will
remain on to illuminate the plants.
2. There are two moisturesensors placed inside the vessels where it will
check the level of moisture ofthe soil that will determine the dryness level
of the plants and based on itwill act a pump that will automatically water
the plants under the greenhouse.The pump will only act when the level of
the liquid inside the tank, thanks tothe presence of the water level sensor
that will allow the measurement, will beabove a certain pre-set threshold
and will take the necessary water forirrigation from a where the sensor that
will measure the level of the liquidwill be placed inside it. This sensor will
allow a buzzer to sound and turn ona red LED only at the end of the liquid
inside the container, it will soundonly in the presence of a movement in
front of the greenhouse determined by thepir. While if the level will be
high you will turn on a green LED. This processwill allow the
construction of a greenhouse that manages completelyautonomously the
plants it guards within them.

Images of the project being built


Images at the end of the project with two plants inside
SCHEMATICS
CODE
#include <Servo.h>
Servo servo;
int level=0;
float temperature=0;
int valhumidity=0;
int detection=0;

int pir=2;
int buzzerPin=3;
int relay1=4;
int relay2=5;
int green=9;
int red=10;

int ldr1;
int ldr2;
int temp;
int waterlevel;
int humidity1;
int humidity2;

void setup(){
Serial.begin(9600);
servo.attach(11);
pinMode(green, OUTPUT);
pinMode(red, OUTPUT);
pinMode(pir, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(waterlevel, INPUT);
pinMode(humidity1, INPUT);
pinMode(humidity2, INPUT);
pinMode(temp, INPUT);
pinMode(ldr1, INPUT);
pinMode(ldr2, INPUT);
}
void loop()
{
temp=analogRead(A2);
temperature =((temp * 0.00488) - 0.5) / 0.01;
detection=digitalRead(pir);
waterlevel=analogRead(A3);

ldr1 = analogRead(A0);
ldr2 = analogRead(A1);
Serial.print("ldr1 is:");
Serial.print(ldr1);
Serial.print(" | ");
Serial.print("ldr2 is:");
Serial.print(ldr2);
Serial.print(" | ");
Serial.print("water level is:");
Serial.println(waterlevel);
Serial.print(" | ");
Serial.print("temperature is:");
Serial.println(temperature);

if((ldr1-ldr2)>=250 || (ldr2-ldr1)>=250) {// vero se una delle due espressioni è vera


if(detection==HIGH)
servo.write(0);
digitalWrite(relay1,HIGH);{
for(int i=1; i<6; i++) {
tone(buzzerPin, 1000, 500);
digitalWrite(red,HIGH);
digitalWrite(green,LOW);
delay(500);
digitalWrite(red,LOW);
delay(500);}
delay(5000);}}

else{
if(((ldr1+ldr2)/2)>700 && temperature>15 ){
servo.write(90);
digitalWrite(relay1,LOW);
delay(1000);}

if(((ldr1+ldr2)/2)<700 || temperature>15 ){
servo.write(0);
digitalWrite(relay1,HIGH);
delay(1000);}

if(waterlevel<180){
digitalWrite(red,HIGH);
digitalWrite(green,LOW);
digitalWrite(relay2,LOW);
if(detection==HIGH){
for(int i=1; i<5; i++) {
tone(buzzerPin, 1000, 500);
delay(1000);}
delay(5000);}}

else{
digitalWrite(green,HIGH);
digitalWrite(red,LOW);
digitalWrite(relay2, LOW);
do{
digitalWrite(relay2, HIGH);
humidity1=analogRead(A4);
humidity2=analogRead(A5);}
while (((humidity1+humidity2)/2)> 500);
digitalWrite(relay2, LOW);
delay(1000);
}}}
130) Arduino Flashing LED Light and Temperature Data Logger
Projet
COMPONENTS AND SUPPLIES
Solid and/or stranded core wire
(assorted colors) × 1

Chanzon LED light chips (full


spectrum) × 1

Chanzon 1W 3W 5W LED heat


spreaders × 1
heat sink for MOSFET
This is screwed on to the
MOSFET on the SSR module. It × 1
is optional, as my MOSFET did
not get too hot.
SparkFun MOSFET Power Control
Kit × 1

aluminum heat sink


× 1

microSD card
For your computer to read the
× 1
chip, you may need a microSD
card adapter.
LPV60-36 constant voltage
controller × 1

DS3231 AT24C32 11C real time


clock module × 1

2-prong power cord


Any old 2-prong power cord will
× 1
do-- just cut it and solder it to the
constant voltage controller.
heat shrink tubing
× 1
For soldering wires together.
microSD card module
× 1

thermal adhesive
× 1

Jumper wires (generic)

× 1

Arduino UNO & Genuino UNO

ABOUT THIS PROJECT


This is a diagram depicts the finished LED light set up, with most of
the connector wires omitted, and with an optional breadboard (green
rectangle) that was added for organizational purposes.
Here's a real-life picture of the light itself (excuse the terrible
soldering)...
and here's a picture of the wiring set-up that controls and powers the
light.
I built this light for a research project that required me to test the effect
of different frequencies of flashing light on the growth of algae. It turns
out that algae is more photosynthetically efficient at certain light
frequencies (this paper outlines an example of the phenomenon and its
importance, if you're interested!). You could test this light out on your
own house plants, or use it in your own science experiment. If there are
any other uses, I'd love to know! Also, I had pretty much zero
experience with electronics before starting this project, so if anyone
has any suggestions for improving the project, or any mistakes I may
have made, please let me know! The light is up and running now, so I
can verify that it works! I'll upload a video soon.
The complete LED light configuration consists of two strands of high-
powered LEDs, wired in parallel and mounted on an aluminum heat
sink. Power is supplied to the light through a 36 V constant-voltage
controller. The frequency of the flashing is directed by an Arduino Uno
microcontroller, through a solid-state relay (SSR). A temperature data
logger is included in the apparatus—it reads the temperature within the
growing area and logs it to an SD card via the Arduino. It can flash at
over 100 hertz.
Begin by measuring the approximate resistance of each LED bulb. This
can be done by wiring each bulb to a 6-volt power source and
measuring the ohms of the bulb with a standard multimeter. Wait
approximately 15 minutes until the LED’s temperature stabilizes,
record the resistance, and label the LEDs. Then, organize the 12 LED
bulbs into 2 groups of 6. The cumulative resistance of the LEDs in each
group should be roughly equivalent, which will help prevent thermal
runaway.
After the LED groups are sorted, begin the assembly of the light. First,
sand the surface of the aluminum heat sink to remove surface oxidation
that could compromise the strength of the thermal adhesive. Mix the
thermal adhesive and spread it in two rows across the heat sink. Then,
place the heat spreaders firmly onto the adhesive in the pattern shown
below.
Solder the LED bulbs onto the heat spreaders, ensuring that the
direction of the diode is aligned with the flow of current through the
spreaders. Test the direction of the diode by wiring the LED to a 5-volt
power source. Try attaching the positive and negative ends of the
power source to different ends of the diode. If the diode lights up, the
side of the diode wired to the positive end of the power supply is the
positive side, and the side wired to the negative end of the power
supply is the negative end. Solder the LEDs as seen below.
Then, cut and strip 12 segments of connector wire. Use these to wire
the LEDs in series, as seen below.

Cut 4 additional 12-inch lengths of connector wire (2 red and two


black). Strip either end of each segment, and wire to the LED array as
seen below.
Then, use a wire nut to connect the two positive (red) wires with a
longer wire. This lead will be connected to the relay, which will in turn
be connected to the constant voltage controller. The length of this wire
is as-needed, depending on the area where the light is set up.
The next step is assembling the SSR (AKA the SparkFun MOSFET
Power Control Kit). Solder the pins into the correct places on the
breadboard, in the configuration seen below. Next, connect the positive
and negative DC leads of the constant voltage power supply to the
positive and negative inputs on the SSR, as seen below. Also solder the
two-pronged power cable to the AC ends of the constant voltage power
supply. Finally, screw the MOSFET heat sink onto the MOSFET
soldered to the breadboard (optional-- my MOSFET didn't end up
getting very hot).
At this point, also attach the positive and negative leads attached to the
light apparatus to the remaining positive and negative ports on the
SSR. All wire lengths can be cut as needed. Also connect the positive
and negative leads of the DC voltage controller to the SSR, as seen
below. The voltage controller serves to keep at least one aspect of the
electricity powering the light constant, to reduce any variations in light
intensity.

Then, connect the SD card modules and DS3231 real-time clock


module to the Arduino Uno. This can be done with jumper wires. A
breadboard could also be used to organize the circuit components. The
pin connections are outlined in the tables below and illustrated in the
following diagram. In addition, connect pin 4 to the gate pin off the
SSR. This is also illustrated in the diagram.

Then, download the DS3231 module library from the


following link. Upload the code to the Arduino Uno via the USB port.
Enter the date, and the hertz at which the light will flash. The flash is
set at a 10 percent duty cycle, but this can also be adjusted.
After uploading the code, insert a micro SD card into the SD card
module. Then, connect the Arduino power supply to the Arduino Uno,
and the main power cord to an AC outlet.

SCHEMATICS
CODE
#include <Wire.h>

#include <DS3231.h> //this library includes functions to be used for the


DS3231 module
#include <SD.h> //this library includes functions to be used for the SD
card module
#include <SPI.h> //this library includes functions that allow for the
communication between the microcontroller and external devices

File tempData; //[defines the variable tempData as a file-type object]


DS3231 rtc(SDA, SCL); //[]
int pinCS = 10; //assigns pin 10 as the Chip Select pin
int gatePin = 4; //assigns pin 4 as the gate pin

void setup(){ //code within setup will only be carried out once

pinMode(gatePin, OUTPUT); //defines gatePin as output

Serial.begin(9600); //sets the rate of data transmission to the Serial


Monitor (Tools > Serial Monitor) at 9600 bits per second
pinMode(pinCS, OUTPUT); //defines pinCS as output

if (SD.begin()){ //initializes the SD card and library and begins use of the
SPI bus and CS pin
Serial.println("ready"); //if the SD card and library are initialized
successfully, the begin function will return True, and "ready" will be
printed to the Serial Monitor
}
else{
Serial.println("failed"); //if the SD card and library are not initialized
successfully, the begin function will return False, and "failed" will be
printed to the Serial Monitor
return; //the return function will stop the rest of the code from running if
the SD card and library fail to initialize
}
rtc.begin(); //initializes the microcontroller's internal real time clock and
RTC library
rtc.setTime(0,0,0); //sets the time (hour, minute, second)
rtc.setDate(30,6,2018); //sets the date [(day, month, year)]
}

int hertz = 1; //creates the variable hertz, which can be altered


float delay_HIGH = (1000/hertz)*0.1; //creates the variable delay_HIGH,
which is dependent on hertz and provides for a 10 percent duty cycle
float delay_LOW = (1000/hertz)*0.9; //creates the variable delay_LOW,
which is dependent on hertz and provides for a 10 percent duty cycle
int max_count = 600*hertz; //creates the variable max_count, which is
dependent on hertz and gives the number of flash cycles that can be
repeated in a 10 minute period

void loop(){
int count = 0;
while (count <= max_count){ //continues the flash cycle for 10 minutes,
or repeats the cycle while the cycle count is less than the number of cycles
in 10 minutes
digitalWrite(gatePin, HIGH); //sends a HIGH signal to the gate of the
MOSFET, powering on the LEDs
delay(delay_HIGH); //keeps the LEDs on for time delay_HIGH
digitalWrite(gatePin, LOW); //sends a LOW signal to the gate of the
MOSFET, powering off the LEDs
delay(delay_LOW); //keeps the LEDs off for time delay_low
count ++; //increments the variable count by one
}
Serial.print(rtc.getDateStr()); //prints the date to the Serial Monitor,
[imported from the internal RTC]
Serial.print(",");
Serial.print(rtc.getTimeStr()); //prints the time to the Serial Monitor,
[imported from the internal RTC]
Serial.print(",");
Serial.println(float(rtc.getTemp())); //prints the temperature to the Serial
Monitor, imported from the DS3231 module

tempData = SD.open("data.txt", FILE_WRITE); //creates the variable


tempData, [which opens/creates the file "data.txt" from the SD card and
allows writing]
if(tempData){ //if the "data.txt" file on the SD card is successfully
opened/created, the following data is written to the file in CSV format
tempData.print(rtc.getDateStr()); //writes the date to "data.txt"
tempData.print(",");
tempData.print(rtc.getTimeStr()); //writes the time to "data.txt"
tempData.print(",");
tempData.println(float(rtc.getTemp())); //writes the temperature to
"data.txt"
tempData.close(); //closes the file "data.txt"
}
else{
Serial.println("error opening file"); //if the "data.txt" file is not
successfully opened/created, "error opening file" is printed to the Serial
Monitor
}
}
131) Arduino and LCDs Projet
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

LCD 16x2
× 1

potenziometer 10K
× 1

Resistor 220 ohm

× 1
jumpers
× 1

Breadboard (generic)

ABOUT THIS PROJECT

How does it work?


The LCDs have a parallel interface, meaning that the microcontroller has
to manipulate several interface pins at once to control the display. The
interface consists of the following pins:
A register select (RS) pin that controls where in the LCD's memory
you're writing data to. You can select either the data register, which
holds what goes on the screen, or an instruction register, which is where
the LCD's controller looks for instructions on what to do next.
A Read/Write (R/W) pin that selects reading mode or writing mode.
An Enable pin that enables writing to the registers.
8 data pins (D0 -D7). The states of these pins (high or low) are the bits
that you're writing to a register when you write, or the values you're
reading when you read.
There's also a display constrast pin (Vo), power supply pins (+5V and
Gnd) and LED Backlight (Bklt+ and BKlt-) pins that you can use to
power the LCD, control the display contrast, and turn on and off the
LED backlight, respectively.
The process of controlling the display involves putting the data that form
the image of what you want to display into the data registers, then putting
instructions in the instruction register. The LiquidCrystal Library
simplifies this for you so you don't need to know the low-level
instructions.
The Hitachi-compatible LCDs can be controlled in two modes: 4-bit or 8-
bit. The 4-bit mode requires seven I/O pins from the Arduino, while the 8-
bit mode requires 11 pins. For displaying text on the screen, you can do
most everything in 4-bit mode, so example shows how to control a 2x16
LCD in 4-bit mode.
2. Schematic
To wire your LCD screen to your Arduino, connect the following pins:
LCD RS pin to digital pin 12
LCD Enable pin to digital pin 11
LCD D4 pin to digital pin 5
LCD D5 pin to digital pin 4
LCD D6 pin to digital pin 3
LCD D7 pin to digital pin 2
Additionally, wire a 10K pot to +5V and GND, with it's wiper (output) to
LCD screens VO pin (pin3).
SCHEMATICS
CODE
/*
LiquidCrystal Library - Hello World

Demonstrates the use a 16x2 LCD display. The LiquidCrystal


library works with all LCD displays that are compatible with the
Hitachi HD44780 driver. There are many of them out there, and you
can usually tell them by the 16-pin interface.

This sketch prints "Hello World!" to the LCD


and shows the time.

The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)

Library originally added 18 Apr 2008


by David A. Mellis
library modified 5 Jul 2009
by Limor Fried (http://www.ladyada.net)
example added 9 Jul 2009
by Tom Igoe
modified 22 Nov 2010
by Tom Igoe

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/LiquidCrystal
*/

// include the library code:


#include

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("hello, world!");
}

void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print(millis()/1000);
}
132) Arduino 2 Way Intersection with Pedestrian Walk Cycle Projet
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO
Tested on the Uno, but easily
× 1
converted for other Arduino
boards
LED (generic)
3 RED, 2 Yellow, 2 Green, and 1 × 8
White

Resistor 221 ohm


Current Limiting resistors, use 8
×
minimum 220 ohms

Resistor 1k ohm

× 1

Resistor 10k ohm


Used as a Pull-Down resistor on 1
×
button

SparkFun Pushbutton switch 12mm


Acts as "Walk Requested" push
button

ABOUT THIS PROJECT


This is a two-way traffic system (USA) that has a main and
an auxillary lighting circuit. Once the walk button is pressed, the
program waits till both circuits return to red before performing a
WALK/DON'T WALK cycle. A software reset guarantees that main will
get the green light first after the walk cycle completes.

SCHEMATICS
CODE
int WalkRequest = 0; // Variable used to store the state of the Walk Push Button
const int WalkButton = 2;
const int RedPedLED = 6;
const int WhitePedLED = 7;

// Setup Variables for Station 1 Traffic Light Components


const int Red1LED = 8;
const int Yellow1LED = 9;
const int Green1LED = 10;

// Setup Variables for Station 2 Traffic Light Components


const int Red2LED = 11;
const int Yellow2LED = 12;
const int Green2LED = 13;

// variables that will change:


volatile int buttonState = 0; // variable for monitoring the pushbutton status.
/* A variable should be declared volatile whenever its value can be changed
by something beyond the control of the code section in which it appears,
such as a concurrently executing thread.
In the Arduino, the only place that this is likely to occur is in sections
of code associated with interrupts, called an interrupt service routine (ISR) */

void setup() {
pinMode(RedPedLED, OUTPUT); // Sets all LED's as OUTPUT
pinMode(WhitePedLED, OUTPUT);
pinMode(Red1LED, OUTPUT);
pinMode(Yellow1LED, OUTPUT);
pinMode(Green1LED, OUTPUT);
pinMode(Red2LED, OUTPUT);
pinMode(Yellow2LED, OUTPUT);
pinMode(Green2LED, OUTPUT);
pinMode(WalkButton, INPUT); // Sets Push Button as INPUT

attachInterrupt(0, pin_ISR, CHANGE); // "Watches" in the background for a button press


/* Attach an interrupt to the ISR vector to monitor Push Button.
Number 0 (for digital pin 2) or number 1 (for digital pin 3) are used.
Interrupts are useful for making things happen automatically in
microcontroller programs,and can help solve timing problems.
Good tasks for using an interrupt may include reading
a rotary encoder, or monitoring user input */

// Set Initial state of all red LED to HIGH


digitalWrite (Red1LED, HIGH);
digitalWrite (Red2LED, HIGH);
digitalWrite (RedPedLED, HIGH);
}

void loop() {
// put your main code here, to run repeatedly:

// Station 1 Timing
delay(2500); // 2.5 Seconds of Red
digitalWrite(Red1LED, LOW); // Sets Red1 OFF Green ON
digitalWrite(Green1LED, HIGH);
delay(15000); // 15 Seconds of Green
digitalWrite(Green1LED, LOW); // Sets Green1 OFF Yellow ON
digitalWrite(Yellow1LED, HIGH);
delay(3500); // 3.5 Seconds of Yellow
digitalWrite(Yellow1LED, LOW); // Sets Yellow1 OFF Red ON
digitalWrite(Red1LED, HIGH);

if (WalkRequest == 1) { // If the button has been pressed


WalkCycle(); // Exit main loop and run WalkCycle () function
}

// Station 2 Timing
delay(2500); // 2.5 Seconds of Red
digitalWrite(Red2LED, LOW); digitalWrite(Green2LED, HIGH); // Sets Red2 OFF Green
ON
delay(15000); // 15 Seconds of Green
digitalWrite(Green2LED, LOW); digitalWrite(Yellow2LED, HIGH); // Sets Green2 OFF
Yellow ON
delay(3500); // 3.5 Seconds of Yellow
digitalWrite(Yellow2LED, LOW); digitalWrite(Red2LED, HIGH); // Sets Yellow2 OFF
Red ON

if (WalkRequest == 1) { // If the button has been pressed


WalkCycle(); // Exit main loop and run WalkCycle () function
}
}

void WalkCycle() {
delay(3500); // 3.5 Second delay before "WALK" begins
digitalWrite (WhitePedLED, HIGH); digitalWrite (RedPedLED, LOW); // Turn on White
Pedestrian Light
delay (15000); // 15 Second delay to allow crossing street
digitalWrite (WhitePedLED, LOW); digitalWrite(WalkButton, LOW); // Turn off White
Pedestrian Light
delay(250);
for (int x = 0; x < 5; x++) { // Flash White Ped LED 5X
digitalWrite(WhitePedLED, HIGH);
delay(250);
digitalWrite(WhitePedLED, LOW);
delay(250);
}
digitalWrite(RedPedLED, HIGH);
WalkRequest = 0; // Reset Push Button
asm volatile (" jmp 0"); // Soft-reset of sketch. Makes sure Station 1 "MAIN" always gets
Green after a walk cycle
}

void pin_ISR() {
buttonState = digitalRead(WalkButton);
(WalkRequest = 1); // Walk button has been pressed
// digitalWrite(WhitePedLED, buttonState); // Test Light for Interrupt use only during
testing!
}
133) Arduino Tallking Clock Projet

COMPONENTS AND SUPPLIES

Adafruit RGB Backlight LCD -


16x2
× 1

Arduino UNO & Genuino UNO


× 1

Resistor 1k ohm

× 3

Resistor 2.21k ohm

× 3

Single Turn Potentiometer- 10k


ohms
× 1

Capacitor 22 µF

× 2

Resistor 47.5k ohm

× 1

General Purpose Transistor NPN

× 1

General Purpose Transistor PNP


× 1

Speaker: 0.25W, 8 ohms

× 1

SparkFun Pushbutton switch 12mm

× 3

SD Socket
× 1

ABOUT THIS PROJECT


This Arduino has the basic knowledge to manage SD card and FAT32,
it also runs 24 hours clock and generates audio signals.
The clock tells the time by playing back tracks from the SD. The SD is
FAT32 formatted. The tracks are wave (.wav) files of 22.050 KHz, 8
bits, mono. Totally 27 files are recordings in language of your choice;
0,1,2...19,20,30,40,50,"hours","minutes",message
The SD card interface is in SPI mode. The ATMEGA328P generates
audio using PWM.
The SD card has to be prepared this way:
Files have to be 22.050 KHz, 8 bits, mono. With short names (max 8
characters).
Format the card with FAT32. No folders or sub-folders.
Copy to the root folder the files one at a time and in this order; 0 to 19
(20 files),20,30,40,50,"hours","minutes","good day" (or any other
message). Totally 27 files. If you make a mistake while copying the
files to the SD it isn't enough to delete a file, you must start again with
formatting the SD. The reason for loading the files one at a time is that
if you load them together the PC sends them to the card in the order it
finds fit, and when the code plays them it picks up the files without
searching for their name.
Circuit Description
The SD Card supply is 3.3V (3-3.6V). The 3.3V and 5V are generated
on the Arduino board. The PWM output is boosted by 2 transistors
push-pull. The signal to the speaker is PWM of 62 KHz and the speaker
outputs the modulated audio only. The speaker should be 8 ohms or
higher. Digital outputs from the Arduino to the SD card use 1K and 2K
resistors to reduce the 5V signals to 3.3V. The pins number are for
ordinary SD card, for MicroSD the pins are different. Link between
Arduino pins 3 and 5 connect 1000 Hz clock from timer 2 to timer 1,
these timers generate 1 minute time base. LCD display and driver has
14 way connector, 10 connections are used, 4 bits data bus is selected.
10K pot adjusts the contrast.
SCHEMATICS
CODE

#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, A0, A1, A2, A3);

const int CS = 10; // SD CS connected to digital pin PD4


const int mosi = 11;
const int clk = 13;
const int ampON = 9; // led connected to digital pin PB0
const int audio = 6; //output D6
const int oc2b = 3; //1000Hz
const int t1 = 5; //1000Hz
const int talk = 2; //talk pushbutton
const int minutes = A4; //minutes advance pushbutton
const int hours = A5; //hours pushbutton
int talkPB=1; // talk pushbutton status
int minutesPB=1; // minutes pushbutton status
int hoursPB=1; // hours pushbutton status

unsigned long loc,BootSector, RootDir, SectorsPerFat, RootDirCluster,


DataSector, FileCluster, FileSize; //
unsigned int BytesPerSector, ReservedSectors, card;
unsigned char fn=1, sdhc=0, SectorsPerCluster, Fats;
unsigned char minute=0, hour=0;

void setup() {
// put your setup code here, to run once:
pinMode(CS, OUTPUT);
pinMode(mosi, OUTPUT);
pinMode(clk, OUTPUT);
pinMode(ampON, OUTPUT);
pinMode(talk, INPUT_PULLUP);
pinMode(minutes, INPUT_PULLUP);
pinMode(hours, INPUT_PULLUP);

lcd.begin(16, 2); // set up the LCD's number of columns and rows:

//spi init
SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0) | _BV(SPR1); // Enable
spi, Master, set clock rate fck/64
SPSR = _BV(SPI2X); //set clock rate fck/64 = 250KHz

//PWM Timer0
OCR0A = 0;
TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); //output in
phase, fast PWM mode
TCCR0B = _BV(CS00); // 16MHz/256 = 62.5KHz
pinMode(audio, OUTPUT);

//1000 Hz - timer2
OCR2A =249;
OCR2B = 125;
TCCR2A = _BV(COM2B1) | _BV(COM2B0) | _BV(WGM21) |
_BV(WGM20); //output B in phase, fast PWM mode
TCCR2B = _BV(WGM22) | _BV(CS22); // set prescaler to 64 and start
the timer
pinMode(oc2b, OUTPUT);
//60 sec - timer1
// OCR1A = 0xEA5F;
TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A0); //
TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS11) | _BV(CS12);
// input T1, PWM mode

digitalWrite(CS, HIGH);
//digitalWrite(ampON, LOW);

InitSD();
if(sdhc){card = 1;}else{card=512;} //SD or SDHC
fat();
if(BytesPerSector!=512){error();}

void loop()
{

talkPB=digitalRead(talk);
if(talkPB==LOW)
{
//read hours
if(hour < 21) {fn=hour; play();}
else if(hour == 20) {fn=20; play();}
else if(hour > 20) {fn=20; play(); fn=hour-20; play();}
fn=24; play(); //read "hours"

//read minutes
if(minute < 21) {fn=minute; play();}
else if(minute == 20) {fn=20; play();}
else if(minute > 20 && minute < 30) {fn=20; play(); fn=minute-20;
play();}
else if(minute == 30) {fn=21; play();}
else if(minute > 30 && minute < 40) {fn=21; play(); fn=minute-30;
play();}
else if(minute == 40) {fn=22; play();}
else if(minute > 40 && minute < 50) {fn=22; play(); fn=minute-40;
play();}
else if(minute == 50) {fn=23; play();}
else if(minute > 50 && minute < 60) {fn=23; play(); fn=minute-50;
play();}
fn=25; play(); //read "minutes"
fn=26; play(); //read message
OCR0A=0; //audio off

minutesPB=digitalRead(minutes);
if(minutesPB==LOW)
{
minute++;
if(minute>59) {minute=0;}
display();
wait();
}

hoursPB=digitalRead(hours);
if(hoursPB==LOW)
{
hour++;
if(hour>23) {hour=0;}
display();
wait();
}

if(TIFR1 & _BV(OCF1A)) //1 minute elapsed


{
OCR1A = 0xEA5F; //59999 counts = 1 minute
TIFR1 = _BV(OCF1A); //TMR1 interrupt reset

minute++;
if(minute>59) {minute=0; hour++;}
if(hour>23) hour=0;
display();

}
}
//find the file and play it
void play(void)
{
if(!sdhc){fn += 1;} //if not SDHC first file = 1
if(fn > 15)
{
fn -=16; file(fn*32+20,1); //32 bytes per file descriptor at offset of 20
}
else
{
file(fn*32+20,0); //32 bytes per file descriptor at offset of 20
}
loc=(1 + (DataSector) + (unsigned long)(FileCluster-2) *
SectorsPerCluster) * card ;
ReadSD();
}

//LCD update
void display(void)
{
lcd.setCursor(5, 0); // top left
if(hour<10)lcd.print(" ");
lcd.print(hour);
lcd.print(":");
if(minute<10)lcd.print("0");
lcd.print(minute);
}
//SD error display
void error(void)
{
lcd.setCursor(0, 1); // bottom left
lcd.print("SD ERROR");
lcd.setCursor(0, 0); // top left
}

//1 sec delay


void wait(void)
{
unsigned long i; //,j
for(i=0;i<100000;i++)
{
digitalWrite(ampON, LOW);
}
}

void ReadSD(void)
{
unsigned int i,r;
unsigned char read_data;
digitalWrite(CS, LOW);
r = Command(18,loc,0xFF); //read multi-sector
if(r != 0) error(); //if command failed error();
while(FileSize--)
{
while(spi(0xFF) != 0xFE); // wait for first byte
for(i=0;i<512;i++){
// 3 rounds of timer 0 = total of time to get 22 khz
while (!(TIFR0 & _BV(OCF0A))){}
TIFR0 = _BV(OCF0A); //TMR0 interrupt reset
while (!(TIFR0 & _BV(OCF0A))){}
TIFR0 = _BV(OCF0A); //TMR0 interrupt reset
while (!(TIFR0 & _BV(OCF0A))){}

OCR0A=spi(0xFF); //write byte to PWM


TIFR0 = _BV(OCF0A); //TMR0 interrupt reset
}
spi(0xFF); //discard of CRC
spi(0xFF);
}

Command(12,0x00,0xFF); //stop transmit


spi(0xFF);
spi(0xFF);
digitalWrite(CS, HIGH);
spi(0xFF);
}

void file(unsigned int offset, unsigned char sect) //find files


{
unsigned int r,i;
unsigned char fc[4], fs[4]; //

digitalWrite(CS, LOW);
r = Command(17,(RootDir+sect)*card,0xFF); //read boot-sector for info
from file entry
if(r != 0) error(); //if command failed

while(spi(0xFF) != 0xFe); // wait for first byte


for(i=0;i<512;i++){
if(i==offset){fc[2]=spi(0xFF);}
else if(i==offset+1){fc[3]=spi(0xFF);}
else if(i==offset+6){fc[0]=spi(0xFF);}
else if(i==offset+7){fc[1]=spi(0xFF);}

else if(i==offset+8){fs[0]=spi(0xFF);}
else if(i==offset+9){fs[1]=spi(0xFF);}
else if(i==offset+10){fs[2]=spi(0xFF);}
else if(i==offset+11){fs[3]=spi(0xFF);}
else{spi(0xFF);}

}
spi(0xFF); //discard of CRC
spi(0xFF);
digitalWrite(CS, HIGH);
spi(0xFF);
FileCluster = fc[0] | ( (unsigned long)fc[1] << 8 ) | ( (unsigned long)fc[2]
<< 16 ) | ( (unsigned long)fc[3] << 24 );
FileSize = fs[0] | ( (unsigned long)fs[1] << 8 ) | ( (unsigned long)fs[2] <<
16 ) | ( (unsigned long)fs[3] << 24 );
FileSize = FileSize/512-1; //file size in sectors
}

void fat (void)


{
unsigned int r,i;
unsigned char pfs[4],bps1,bps2,rs1,rs2,spf[4],rdc[4]; //pfs=partition first
sector ,de1,de2,spf1,d[7]

digitalWrite(CS, LOW);
r = Command(17,0,0xFF); //read MBR-sector
if(r != 0) error(); //if command failed

while(spi(0xFF) != 0xFe); // wait for first byte


for(i=0;i<512;i++){
if(i==454){pfs[0]=spi(0xFF);} //pfs=partition first sector
else if(i==455){pfs[1]=spi(0xFF);}
else if(i==456){pfs[2]=spi(0xFF);}
else if(i==457){pfs[3]=spi(0xFF);}
else{spi(0xFF);}

}
spi(0xFF); //discard of CRC
spi(0xFF);
digitalWrite(CS, HIGH);
spi(0xFF);
//convert 4 bytes to long int
BootSector = pfs[0] | ( (unsigned long)pfs[1] << 8 ) | ( (unsigned
long)pfs[2] << 16 ) | ( (unsigned long)pfs[3] << 24 );

digitalWrite(CS, LOW);
r = Command(17,BootSector*card,0xFF); //read boot-sector
if(r != 0) error(); //if command failed

while(spi(0xFF) != 0xFe); // wait for first byte


for(i=0;i<512;i++){

if(i==11){bps1=spi(0xFF);} //bytes per sector


else if(i==12){bps2=spi(0xFF);}
else if(i==13){SectorsPerCluster=spi(0xFF);}
else if(i==14){rs1=spi(0xFF);}
else if(i==15){rs2=spi(0xFF);}
else if(i==16){Fats=spi(0xFF);} //number of FATs
else if(i==36){spf[0]=spi(0xFF);}
else if(i==37){spf[1]=spi(0xFF);}
else if(i==38){spf[2]=spi(0xFF);}
else if(i==39){spf[3]=spi(0xFF);}
else if(i==44){rdc[0]=spi(0xFF);}
else if(i==45){rdc[1]=spi(0xFF);}
else if(i==46){rdc[2]=spi(0xFF);}
else if(i==47){rdc[3]=spi(0xFF);}
else{spi(0xFF);}

}
spi(0xFF); //discard of CRC
spi(0xFF);
digitalWrite(CS, HIGH);
spi(0xFF);

BytesPerSector = bps1 | ( (unsigned int)bps2 << 8 );


ReservedSectors = rs1 | ( (unsigned int)rs2 << 8 ); //from partition start to
first FAT
RootDirCluster = rdc[0] | ( (unsigned long)rdc[1] << 8 ) | ( (unsigned
long)rdc[2] << 16 ) | ( (unsigned long)rdc[3] << 24 );
SectorsPerFat = spf[0] | ( (unsigned long)spf[1] << 8 ) | ( (unsigned
long)spf[2] << 16 ) | ( (unsigned long)spf[3] << 24 );
DataSector = BootSector + (unsigned long)Fats * (unsigned
long)SectorsPerFat + (unsigned long)ReservedSectors; // + 1
RootDir = (RootDirCluster -2) * (unsigned long)SectorsPerCluster +
DataSector;
}

unsigned char spi(unsigned char data) // send character over spi


{
SPDR = data; // Start transmission
while(!(SPSR & _BV(SPIF))); // Wait for transmission to complete
return SPDR; // received byte

}
//assemble a 32 bits command
char Command(unsigned char frame1, unsigned long adrs, unsigned char
frame2 )
{
unsigned char i, res;
spi(0xFF);
spi((frame1 | 0x40) & 0x7F); //first 2 bits are 01
spi((adrs & 0xFF000000) >> 24); //first of the 4 bytes address
spi((adrs & 0x00FF0000) >> 16);
spi((adrs & 0x0000FF00) >> 8);
spi(adrs & 0x000000FF);
spi(frame2 | 1); //CRC and last bit 1

for(i=0;i<10;i++) // wait for received character


{
res = spi(0xFF);
if(res != 0xFF)break;
}
return res;
}

void InitSD(void)
{
unsigned char i,r[4];

digitalWrite(CS, HIGH);
for(i=0; i < 10; i++)spi(0xFF); // min 74 clocks
digitalWrite(CS, LOW); // Enabled for spi mode

i=100; //try idle state for up to 100 times


while(Command(0x00,0,0x95) !=1 && i!=0)
{
digitalWrite(CS, HIGH);
spi(0xFF);
digitalWrite(CS, LOW);
i--;
}
if(i==0) error(); //idle failed

if (Command(8,0x01AA,0x87)==1){ //check card is 3.3V


r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); r[3]=spi(0xFF); //rest of
R7
if ( r[2] == 0x01 && r[3] == 0xAA ){ //Vdd OK (3.3V)

//Command(59,0,0xFF); //CRC off


Command(55,0,0xFF);
while(Command(41,0x40000000,0xFF)){Command(55,0,0xFF);}
//ACMD41 with HCS bit
}
}else{error();}

if (Command(58,0,0xFF)==0){ //read CCS in the OCR - SD or SDHC


r[0]=spi(0xFF); r[1]=spi(0xFF); r[2]=spi(0xFF); r[3]=spi(0xFF); //rest of
R3
sdhc=r[0] & 0x40;
//if(r[0] & 0x40)sdLED=1;
}
SPCR &= ~(_BV(SPR1)); // set clock rate fck/8 = 2MHz
digitalWrite(CS, HIGH);
}
134) Arduino Remote Controlled Smart Lamp Projet

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Infrared (IR) Proximity / Obstacle


Detecting Sensor Module ×

ABOUT THIS PROJECT


Its amazing that you can easily control any appliances through any of your
old/new Remote. As we have developed this project cost effective too, so
we've used relay and an IR sensor only, which costs less than $5.
Working!
First you need to go to this page and download the IR library. You just
need to follow the read me file to install. I think that any IR remote control
can do this, I’ll be using a Philips Universal one. The infrared receiver has
3 pins:
First pin: Vout, outputs HIGH when no signal is present and LOW when a
mark is received.
Second pin: GND.
Third pin: Vcc.
Connect relay pins:
Gnd( A ) with Arduino Gnd
Middle pin(A/C) pole with AC power as given in circuit.
RELAY NO Pin with One lamp pin(wire)
RELAY ( B ) with lamp another pin(wire)
Now you will get two wires as shown in given below figure, one from
relay side and another from lamp (bulb) side connect to ac (but wait
here.). Circuit Diagram:
You need to wire your circuit something like this. And then COPY AND
PASTE BELOW GIVEN CODE in Arduino then upload it:
/*Created By: Anshul Pareek
*usage : read IR SIGNALS AND PRINT ON SERIAL
*/
#include <boarddefs.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
#include <IRremote.h>
#include <IRremoteInt.h>
int RECV_PIN = 9;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results))
{

Serial.println(results.value);

irrecv.resume(); // Receive the next value


}
delay(000);
}
Open your serial port by going tools->serial monitor. When you run this
code and pressing remote buttons you'll see some of the codes of your
remote buttons like as. I've received POWER button code as: 490607474
VOLUME UP: 1053668050 Write these code somewhere for our
upcoming code below. After remembering above code use in below given
code in condition part:
/*Light on off code*/
#include <boarddefs.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
#include <IRremote.h>
#include <IRremoteInt.h>
int RECV_PIN = 9;
int OUT_PIN=8;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
pinMode(OUT_PIN,OUTPUT);
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results))
{
Serial.println(results.value);
if(results.value == 490607474){ //Please replace your remote button
code for which you want to on the light
digitalWrite(OUT_PIN,HIGH);
delay(1000);
}else{
digitalWrite(OUT_PIN,LOW);
}
delay(1000);
irrecv.resume(); // Receive the next value
}

delay(000);
}
Now upload above code in Arduino and run this code. If everything is
alright your lights will glow and off with your remote buttons. As I am
controlling only one Bulb only but you can control more than one bulb
using different pins and relays and please beware about the AC
Connections. We are going to Launch more interesting clone of this
project soon.
SCHEMATICS

CODE
Arduino check Remote CodeArduino
Check remote codes using this code
/*Created By: Anshul Pareek
*usage : read IR SIGNALS AND PRINT ON SERIAL
*/
#include <boarddefs.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
#include <IRremote.h>
#include <IRremoteInt.h>
int RECV_PIN = 9;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{

Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results))
{

Serial.println(results.value);

irrecv.resume(); // Receive the next value


}
delay(000);
}
Arduino Switch light on offArduino
Use this code to switch on off the light remember to replace remote
button code.

/*Light on off code*/


#include <boarddefs.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
#include <IRremote.h>
#include <IRremoteInt.h>
int RECV_PIN = 9;
int OUT_PIN=8;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
pinMode(OUT_PIN,OUTPUT);
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results))
{
Serial.println(results.value);
if(results.value == 490607474){ //Please replace your remote button code for which you
want to on the light
digitalWrite(OUT_PIN,HIGH);
delay(1000);
}else{
digitalWrite(OUT_PIN,LOW);
}
delay(1000);
irrecv.resume(); // Receive the next value
}

delay(000);
}
135) Arduino Binary Counting Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1
Solderless Breadboard Full Size
× 1

Male/Male Jumper Wires


× 12

LED (generic)

× 6

SparkFun Pushbutton switch


12mm
× 2

10 ohm resistor
× 2

ABOUT THIS PROJECT


binary numbers is a form of digits using 1 and 0. Their combination
brings a natural number. for eg. binary number 101 is 5, 1101 is 13 and
11100 is 28 on which computer field depends upon. I tried to make it to
startup in this open field.
It uses 6 LEDs to use on the positions of values 32,16,8,4,2,1
respectively (eg. - 000101 is 5)
THINGS YOU NEED TO HAVE:-
1 arduino uno r3
1 bread board

12 jumper wires
6 LED
1 button switch(tactile)
initiate following steps from photos to build it(for more reference see
circuit diagram).

SCHEMATICS

CODE
int l[]={0,0,0,0,0,0},T=6,a,p;
const int b1=12,b2=13;
void setup() {
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
pinMode(b1,INPUT);
pinMode(b2,INPUT);
}
void loop() {
p=0;
p=digitalRead(b1) ;
while(digitalRead(b1)!=0)
{

}
delay(100);
a=T-1;
while(a>=0&&p==1)
{
if(l[a]==1)
{
l[a]=0;
a--;
}
else
{
l[a]=1;
p=0;
}
}
p=digitalRead(b2) ;
while(digitalRead(b2)!=0)
{

}
delay(100);
a=T-1;
while(a>=0&&p==1)
{
if(l[a]==0)
{
l[a]=1;
a--;
}
else
{
l[a]=0;
p=0;
}
}
a=T-1;
for(int c=0;c<T;c++)
{
if(l[c]==1)
digitalWrite(T-c+1,HIGH);
else
digitalWrite(T-c+1,LOW);
a--;
}
}

136) Stopwatch with Arduino Starter Kit Projet


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1
Rotary potentiometer (generic)

× 1

SparkFun Pushbutton switch 12mm

× 2

Jumper wires (generic)

× 20

Resistor 221 ohm

× 1

Resistor 10k ohm

× 2

ABOUT THIS PROJECT


Build from the ground up and improve step by step:
1. learn millis() and LCD (project book project 8 and 11)
2. program to enable timming and display
3. install two switches to realize start(button 1) and reset(button 2)
function
4. add stop function to button 1
5. change stop function to pause function
6. add lap&display function to button 2 when timing
7. improve the stopwatch by display timming at row 0 col 0, display
lap spilts at row 0 col 1 and row 1 col 1

SCHEMATICS

CODE
//function: stopwatch with start/stop(button 1) and reset(button 2)
//start/pause button 1
//add lap function success!!
//improve lap function scuuess!!
#include<LiquidCrystal.h>
LiquidCrystal lcd(12,11,7,6,5,4);

int ss1 = 0, ss2 = 0;


int pss1 = 0;
int ms=0,sec =0, minute=0;
long interval = 98;
unsigned long last=0,dur,pre=0,last2=0,dur2;
int num_rise=0;
bool reset=0,row=0;

void timeNprint(){
unsigned long curr = millis();
if (curr-pre>interval){
pre=curr;
ms++;
if (ms==10) {sec++;ms=0;}
if (sec==60) {sec=0;minute++;}
lcd.setCursor(0,0);
if (minute<10) lcd.print("0");
lcd.print(minute);
lcd.print(":");
if (sec<10) lcd.print("0");
lcd.print(sec);
lcd.print(":");
lcd.print(ms);
}
}
void printTime(){
lcd.setCursor(9,row);
row=!row;
if (minute<10) lcd.print("0");
lcd.print(minute);
lcd.print(":");
if (sec<10) lcd.print("0");
lcd.print(sec);
lcd.print(":");
lcd.print(ms);
}
void resetNwelcome(){
ms=0;minute=0;sec=0;
lcd.setCursor(0,1);
lcd.print("XW's Stopwatch");
lcd.setCursor(0,0);
lcd.print("Welcome to use");
}

void setup() {
lcd.begin(16,2);
pinMode(2,INPUT);
pinMode(3,INPUT);
}

void loop() {
num_rise=0;
resetNwelcome();
ss1=digitalRead(2);
if (ss1 == HIGH)
{
num_rise++;
last=millis();
lcd.clear();
while(1) //stop
{
switch(num_rise%2)
{
case 0: //pause
ss2=digitalRead(3);
ss1=digitalRead(2);
dur=millis()-last;
if (ss2==HIGH) {reset=1;break;}
else if(ss1==HIGH && dur>300) {
num_rise++;
last=millis();}
break;
case 1:
timeNprint();
ss1=digitalRead(2);dur=millis()-last;
if (ss1==HIGH &&dur>300) {
num_rise++;
last=millis();
}
break;

}
ss2=digitalRead(3);
dur2=millis()-last2;
if(ss2==1 && dur2>300)
{
last2=millis();
printTime();
}
if(reset==1)
{reset=0;lcd.clear();row=0;break;}
}
}
}
137) Arduino Robot Joystick Board Recording Movements Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO
× 1

MeArm joystick board (version 1.6.1)


× 1

Infrared module KY-022


× 1
It is not necessary
Micro servo SG90
× 4
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


This project uses a MeArm v1.6.1 joystick board.

Joystick board MeArm v1.6.1


Allows 4 modes:
Manual mode
Recording of coordinates - indicated by permanent light of LED
diode.
Play mode - play once recorded movements
Play repeatedly - plays recorded movements repeatedly - indicated
by flashing of LED diode.
Press button on joistick 1 to Start/Stop of recording coordinates.
Press button on joistick 2 to Start/Stop of play coordinates.
Press and hold button for 2 seconds on joistick 2 to Start/Stop of play
coordinates repeatedly.

SCHEMATICS
CODE
/* meArm analog joysticks version 1.6.1.4 - UtilStudio.com Jan 2019
Uses two analogue joysticks and four servos.

Version 1.6.1.x is targeted to MeArm Joystick board version 1.6.1.

First joystick moves gripper forwards, backwards, left and right,


button start/stop recording positions.

Second joystick moves gripper up, down, and closes and opens,
button start/stop playing recorded positions.
Press button for 2 seconds to autoplay.

Please send a short message as a feedback, if you uses this code.


Thank you. ;-)

Pins:
Arduino Stick1 Stick2 Base Shoulder Elbow Gripper Record/ Infrared
GND GND GND Brown Brown Brown Brown Auto play sensor
5V VCC VCC Red Red Red Red LED
A0 HOR
A1 VER
PD2 BUTT
A2 HOR
A3 VER
PD4 BUTT
11 Yellow
10 Yellow
9 Yellow
5 Yellow
PD3 X
12 X
*/
//#define infraredSensor true; // Uncomment this line, if you want to use Infrared controller.

/*
And replace codes of infrared controller with your own codes in function
CheckIrController.
Set debug to true and use a Serial monitor of your Arduino IDE to show received codes of
your remote controller.
*/

#include <Servo.h>

#if defined infraredSensor


#include <IRremote.h>
#endif

bool debug = false;

bool repeatePlaying = false; /* Repeatedly is running recorded cycle */


int delayBetweenCycles = 2000; /* Delay between cycles */

const int basePin = 11; /* Base servo */


const int shoulderPin = 10; /* Shoulder servo */
const int elbowPin = 9; /* Elbow servo */
const int gripperPin = 5; /* Gripper servo - changed */

int xdirPin = 0; /* Base - joystick1*/


int ydirPin = 1; /* Shoulder - joystick1 */
int zdirPin = 2; /* Elbow - joystick2 */
int gdirPin = 3; /* Gripper - joystick2 */

int pinRecord = PD2; /* Button record */


int pinPlay = PD4; /* Button play - changed */
int pinLedRecord = PD3; /* LED - indicates recording (light) or auto play mode (blink
ones) - changed */

int RECV_PIN = 12; /* Infrared sensor */

const int buffSize = 412; /* Size of recording buffer */

int startBase = 90;


int startShoulder = 42;
int startElbow = 50;
int startGripper = 30;

int posBase = 90;


int posShoulder = 90;
int posElbow = 90;
int posGripper = 90;

int lastBase = 90;


int lastShoulder = 90;
int lastElbow = 90;
int lastGripper = 90;

int minBase = 0;
int maxBase = 150;
int minShoulder = 25;
int maxShoulder = 135;
int minElbow = 10;
int maxElbow = 118;
int minGripper = 10;
int maxGripper = 61;

const int countServo = 4;


byte currentPos[countServo] = {
0, 0, 0, 0};
byte lastPos[countServo] = {
255, 255, 255, 255};
byte minPos[countServo] = {
minBase, minShoulder, minElbow, minGripper};
byte maxPos[countServo] = {
maxBase, maxShoulder, maxElbow, maxGripper};
int servoPin[countServo] = {
basePin, shoulderPin, elbowPin, gripperPin};

uint16_t buff[buffSize];
uint16_t buffAdd[countServo];
int recPos = 0;
int playPos = 0;
int blockPlayPos = 0;

int buffPos = 0;

struct tPlayBuff
{
byte ServoNumber;
byte Angle;
};

tPlayBuff playBuff[countServo];
int playBuffCount = 0;
byte cyclesRecord = 0;
byte cyclesPlay = 0;

int buttonRecord = HIGH;


int buttonPlay = HIGH;

int buttonRecordLast = LOW;


int buttonPlayLast = LOW;

bool record = false;


bool play = false;

String command = "Manual";


int printPos = 0;

int buttonPlayDelay = 20;


int buttonPlayCount = 0;

bool ledLight = false;

int servoTime = 0;

float dx = 0;
float dy = 0;
float dz = 0;
float dg = 0;

Servo servoBase;
Servo servoShoulder;
Servo servoElbow;
Servo servoGripper;

#if defined infraredSensor


IRrecv irrecv(RECV_PIN);

decode_results results;

// Please, replace codes of infrared controller with your own codes


// in function CheckIrController
void CheckIrController()
{
if (irrecv.decode(&results))
{
switch (results.value)
{
case 0xBE15326E:
case 0xDB9D3097:
dx = 5;
break;
case 0x9912B99A:
case 0x9FA96F:
dx = -5;
break;
case 0xE5139CA7:
case 0xAC516266:
dy = 5;
break;
case 0xE4139B12:
case 0xAD5163FB:
dy = -5;
break;
case 0x21:
case 0x821:
dz = -5;
break;
case 0x20:
case 0x820:
dz = 5;
break;
case 0x11:
case 0x811:
dg = -5;
break;
case 0x10:
case 0x810:
dg = 5;
break;
case 0x1C102884:
case 0x4B995E59:
buttonRecord = !buttonRecord;
break;
case 0xC460AC26:
case 0x6626F67F:
buttonPlay = !buttonPlay;
break;
case 0xDF50BC53:
case 0xF04EE0E6:
repeatePlaying = !repeatePlaying;

if (repeatePlaying)
{
record = false;
play = true;
}
else
{
play = false;
}
break;
}
}
}
#endif

void setup() {
Serial.begin(9600);

pinMode(xdirPin, INPUT);
pinMode(ydirPin, INPUT);
pinMode(zdirPin, INPUT);
pinMode(gdirPin, INPUT);

pinMode(pinRecord, INPUT_PULLUP);
pinMode(pinPlay, INPUT_PULLUP);

pinMode(pinLedRecord, OUTPUT);

servoBase.attach(basePin);
servoShoulder.attach(shoulderPin);
servoElbow.attach(elbowPin);
servoGripper.attach(gripperPin);

StartPosition();

#if defined infraredSensor


irrecv.enableIRIn(); // Start the receiver
#endif

digitalWrite(pinLedRecord, HIGH);
delay(1000);
digitalWrite(pinLedRecord, LOW);
}

void loop() {
buttonRecord = digitalRead(pinRecord);
buttonPlay = digitalRead(pinPlay);
dx = 0;
dy = 0;
dz = 0;
dg = 0;

#if defined infraredSensor


CheckIrController();

if (debug)
{
Serial.println(results.value, HEX);
}

irrecv.resume(); // Receive the next value


#endif

// Serial.print(buttonRecord);
// Serial.print("\t");
// Serial.println(buttonPlay);
// for testing purposes

if (buttonPlay == LOW)
{
buttonPlayCount++;

if (buttonPlayCount >= buttonPlayDelay)


{
repeatePlaying = true;
}
}
else buttonPlayCount = 0;

if (buttonPlay != buttonPlayLast)
{
if (record)
{
record = false;
}

if (buttonPlay == LOW)
{
play = !play;
repeatePlaying = false;

if (play)
{
// StartPosition();
}
}
buttonPlayLast = buttonPlay;
}

if (buttonRecord != buttonRecordLast)
{
if (buttonRecord == LOW)
{
record = !record;

if (record)
{
play = false;
repeatePlaying = false;
recPos = 0;
cyclesRecord = 0;
}
else
{
if (debug) PrintBuffer();
}
}
buttonRecordLast = buttonRecord;
}

if (repeatePlaying)
{
play = true;
}

if (dx == 0) dx = map(analogRead(xdirPin), 0, 1023, 3.5, -3.5);


if (dy == 0) dy = map(analogRead(ydirPin), 0, 1023, 4.0, -4.0);
if (dz == 0) dz = map(analogRead(zdirPin), 0, 1023, 4.0, -4.0);
if (dg == 0) dg = map(analogRead(gdirPin), 0, 1023, -4.0, 4.0);

if (abs(dx) < 1.5) dx = 0;


if (abs(dy) < 1.5) dy = 0;
if (abs(dz) < 1.5) dz = 0;
if (abs(dg) < 1.5) dg = 0;

posBase += dx;
posShoulder += dy;
posElbow += dz;
posGripper += dg;

if ((play) | (cyclesPlay > 0))


{
if (cyclesPlay > 0)
{
cyclesPlay--;

if (cyclesPlay > 0)
{
if (play)
{
playPos = blockPlayPos;
}
else
{
play = false;
}
}
}

if (play)
{
if (playPos >= recPos)
{
playPos = 0;

if (repeatePlaying)
{
if (debug)
{
Serial.println("Auto start ");
}

delay(delayBetweenCycles);
// StartPosition();
}
else
{
play = false;
repeatePlaying = false;
}
}

blockPlayPos = playPos;
playBuffCount = 0;
bool endOfData = false;

while (!endOfData)
{
if (playPos >= buffSize - 1) break;
if (playPos >= recPos) break;

uint16_t data = buff[playPos];


byte angle = data & 0xFF;
uint16_t servoNumber = data & 0xf00;
endOfData = data & 0x8000;
uint16_t repeatCycles = data & 0x7000;
repeatCycles = repeatCycles >> 12;

if (play & cyclesPlay <= 0)


{
cyclesPlay = repeatCycles;
}

servoNumber = servoNumber >> 8;

playBuff[playBuffCount].ServoNumber = servoNumber;
playBuff[playBuffCount].Angle = angle;

playBuffCount++;

switch (servoNumber)
{
case 0:
posBase = angle;
break;

case 1:
posShoulder = angle;
break;

case 2:
posElbow = angle;
break;

case 3:
posGripper = angle;
dg = posGripper - lastGripper;
break;
}
// if (debug)
// {
// Serial.print("Play data ");
// Serial.print(data, BIN);
// Serial.print(" servo ");
// Serial.print(servoNumber);
// Serial.print(" angle ");
// Serial.print(angle);
// Serial.print(" end=");
// Serial.println(endOfData);
// }
//

playPos++;

if (playPos >= recPos)


{
play = false;

break;
}
}
}
}
else
{
cyclesPlay = 0;
}

if (posBase > maxBase) posBase = maxBase;


if (posShoulder > maxShoulder) posShoulder = maxShoulder;
if (posElbow > maxElbow) posElbow = maxElbow;
if (posGripper > maxGripper) posGripper = maxGripper;

if (posBase < minBase) posBase = minBase;


if (posShoulder < minShoulder) posShoulder = minShoulder;
if (posElbow < minElbow) posElbow = minElbow;
if (posGripper < minGripper) posGripper = minGripper;

bool waitGripper = false;


if (dg < 0) {
posGripper = minGripper;
waitGripper = true;
}
else if (dg > 0) {
posGripper = maxGripper;
waitGripper = true;
}

if (play && waitGripper)


{
delay(1000);
}

currentPos[0] = posBase;
currentPos[1] = posShoulder;
currentPos[2] = posElbow;
currentPos[3] = posGripper;

bool positionChanged = false;

if ((play) | (cyclesPlay > 0))


{
for (int i = 0; i < playBuffCount; i++)
{
MoveServo(servoPin[playBuff[i].ServoNumber], playBuff[i].Angle, servoTime);
}
}
else {
for (int i = 0; i < countServo; i++)
{
if (currentPos[i] > maxPos[i]) currentPos[i] = maxPos[i];
if (currentPos[i] < minPos[i]) currentPos[i] = minPos[i];

if (currentPos[i] != lastPos[i])
{
positionChanged = true;
MoveServo(servoPin[i], currentPos[i], servoTime);
}
}
}

if (positionChanged)
{
if (record)
{
buffPos = 0;
cyclesRecord = 0;

for (int i = 0; i < countServo; i++)


{
if (lastPos[i] != currentPos[i])
{
uint16_t value = (currentPos[i] | (0x100 * i)) & 0x0FFF;
buffAdd[buffPos] = value;
buffPos++;
}
}
buffAdd[buffPos - 1] = buffAdd[buffPos - 1] | 0x8000;

AddToBuff();
}
}
else
{
if (record)
{
if (recPos > 0)
{
cyclesRecord ++;

bool added = false;


bool first = true;

for (int i = recPos - 1; i >= 0; i--)


{
bool endOfData = buff[i] & 0x8000;

if (!first && endOfData) break;

if (cyclesRecord > 7)
{
cyclesRecord = 0;

AddToBuff();
added = true;
}

if (!added) {
uint16_t val = cyclesRecord & 7;
val = val << 12;
val = val & 0x7000;

buff[i] = buff[i] & 0x8FFF;


buff[i] = buff[i] | val;

// if (debug)
// {
// Serial.print(" i=");
// Serial.print(i);
// Serial.print(" Buff[i]=");
// Serial.print(buff[i], BIN);
// Serial.print(" val=");
// Serial.println(val, BIN);
// }

first = false;
}
}
}
}
}

lastBase = posBase;
lastShoulder = posShoulder;
lastElbow = posElbow;
lastGripper = posGripper;

for (int i = 0; i < countServo; i++)


{
lastPos[i] = currentPos[i];
}

if ( repeatePlaying)
{
ledLight = !ledLight;
}
else
{
if (ledLight)
{
ledLight = false;
}

if (record)
{
ledLight = true;
}
};

digitalWrite(pinLedRecord, ledLight);
delay(50);
}
void AddToBuff()
{
for (int i = 0; i < buffPos; i++)
{
buff[recPos + i] = buffAdd[i];
}

recPos += buffPos;

if (recPos >= buffSize - countServo)


{
record = false;
}
}

void MoveServo(uint8_t idServo, int angle, int timeMs)


{
switch (idServo)
{
case basePin:
servoBase.write(angle);
break;
case shoulderPin:
servoShoulder.write(angle);
break;
case elbowPin:
servoElbow.write(angle);
break;
case gripperPin:
servoGripper.write(angle);
break;
}

if (debug)
{
if (record) Serial.print(" Record ");
if (play) Serial.print(" Play ");
if (repeatePlaying) Serial.print(" Auto ");

Serial.print(" Servo ");


Serial.print(idServo);
Serial.print(" Angle ");
Serial.println(angle);
}
}
void PrintBuffer()
{
for (int i = 0; i < recPos; i++)
{
uint16_t data = buff[i];
byte angle = data & 0xFF;
uint16_t servoNumber = data & 0xF00;
servoNumber = servoNumber >> 8;
bool endOfData = data & 0x8000;

Serial.print("Servo=");
Serial.print(servoNumber, HEX);
Serial.print("\tAngle=");
Serial.print(angle);
Serial.print("\tEnd=");
Serial.print(endOfData);
Serial.print("\tData=");
Serial.print(data, BIN);
Serial.println();
}
}

void StartPosition()
{
int angleBase = servoBase.read();
int angleShoulder = servoShoulder.read();
int angleElbow = servoElbow.read();
int angleGripper = servoGripper.read();

Serial.print(angleBase);
Serial.print("\t");
Serial.print(angleShoulder);
Serial.print("\t");
Serial.print(angleElbow);
Serial.print("\t");
Serial.print(angleGripper);
Serial.println("\t");

posBase = startBase;
posShoulder = startShoulder;
posElbow = startElbow;
posGripper = startGripper;

servoBase.write(posBase);
servoShoulder.write(posShoulder);
servoElbow.write(posElbow);
servoGripper.write(posGripper);
}

137) Arduino Robot Joystick Board Recording Movements Projet


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

MeArm joystick board (version 1.6.1)


× 1

Infrared module KY-022


× 1
It is not necessary
Micro servo SG90
× 4
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


This project uses a MeArm v1.6.1 joystick board.

Joystick board MeArm v1.6.1


Allows 4 modes:
Manual mode
Recording of coordinates - indicated by permanent light of LED
diode.
Play mode - play once recorded movements
Play repeatedly - plays recorded movements repeatedly - indicated
by flashing of LED diode.
Press button on joistick 1 to Start/Stop of recording coordinates.
Press button on joistick 2 to Start/Stop of play coordinates.
Press and hold button for 2 seconds on joistick 2 to Start/Stop of play
coordinates repeatedly.

SCHEMATICS
CODE
/* meArm analog joysticks version 1.6.1.4 - UtilStudio.com Jan 2019
Uses two analogue joysticks and four servos.

Version 1.6.1.x is targeted to MeArm Joystick board version 1.6.1.

First joystick moves gripper forwards, backwards, left and right,


button start/stop recording positions.

Second joystick moves gripper up, down, and closes and opens,
button start/stop playing recorded positions.
Press button for 2 seconds to autoplay.

Please send a short message as a feedback, if you uses this code.


Thank you. ;-)

Pins:
Arduino Stick1 Stick2 Base Shoulder Elbow Gripper Record/ Infrared
GND GND GND Brown Brown Brown Brown Auto play sensor
5V VCC VCC Red Red Red Red LED
A0 HOR
A1 VER
PD2 BUTT
A2 HOR
A3 VER
PD4 BUTT
11 Yellow
10 Yellow
9 Yellow
5 Yellow
PD3 X
12 X
*/
//#define infraredSensor true; // Uncomment this line, if you want to use Infrared controller.

/*
And replace codes of infrared controller with your own codes in function
CheckIrController.
Set debug to true and use a Serial monitor of your Arduino IDE to show received codes of
your remote controller.
*/

#include <Servo.h>

#if defined infraredSensor


#include <IRremote.h>
#endif

bool debug = false;

bool repeatePlaying = false; /* Repeatedly is running recorded cycle */


int delayBetweenCycles = 2000; /* Delay between cycles */

const int basePin = 11; /* Base servo */


const int shoulderPin = 10; /* Shoulder servo */
const int elbowPin = 9; /* Elbow servo */
const int gripperPin = 5; /* Gripper servo - changed */

int xdirPin = 0; /* Base - joystick1*/


int ydirPin = 1; /* Shoulder - joystick1 */
int zdirPin = 2; /* Elbow - joystick2 */
int gdirPin = 3; /* Gripper - joystick2 */

int pinRecord = PD2; /* Button record */


int pinPlay = PD4; /* Button play - changed */
int pinLedRecord = PD3; /* LED - indicates recording (light) or auto play mode (blink
ones) - changed */

int RECV_PIN = 12; /* Infrared sensor */

const int buffSize = 412; /* Size of recording buffer */

int startBase = 90;


int startShoulder = 42;
int startElbow = 50;
int startGripper = 30;

int posBase = 90;


int posShoulder = 90;
int posElbow = 90;
int posGripper = 90;

int lastBase = 90;


int lastShoulder = 90;
int lastElbow = 90;
int lastGripper = 90;

int minBase = 0;
int maxBase = 150;
int minShoulder = 25;
int maxShoulder = 135;
int minElbow = 10;
int maxElbow = 118;
int minGripper = 10;
int maxGripper = 61;

const int countServo = 4;


byte currentPos[countServo] = {
0, 0, 0, 0};
byte lastPos[countServo] = {
255, 255, 255, 255};
byte minPos[countServo] = {
minBase, minShoulder, minElbow, minGripper};
byte maxPos[countServo] = {
maxBase, maxShoulder, maxElbow, maxGripper};
int servoPin[countServo] = {
basePin, shoulderPin, elbowPin, gripperPin};

uint16_t buff[buffSize];
uint16_t buffAdd[countServo];
int recPos = 0;
int playPos = 0;
int blockPlayPos = 0;

int buffPos = 0;

struct tPlayBuff
{
byte ServoNumber;
byte Angle;
};

tPlayBuff playBuff[countServo];
int playBuffCount = 0;
byte cyclesRecord = 0;
byte cyclesPlay = 0;

int buttonRecord = HIGH;


int buttonPlay = HIGH;

int buttonRecordLast = LOW;


int buttonPlayLast = LOW;

bool record = false;


bool play = false;

String command = "Manual";


int printPos = 0;

int buttonPlayDelay = 20;


int buttonPlayCount = 0;

bool ledLight = false;

int servoTime = 0;

float dx = 0;
float dy = 0;
float dz = 0;
float dg = 0;

Servo servoBase;
Servo servoShoulder;
Servo servoElbow;
Servo servoGripper;

#if defined infraredSensor


IRrecv irrecv(RECV_PIN);

decode_results results;

// Please, replace codes of infrared controller with your own codes


// in function CheckIrController
void CheckIrController()
{
if (irrecv.decode(&results))
{
switch (results.value)
{
case 0xBE15326E:
case 0xDB9D3097:
dx = 5;
break;
case 0x9912B99A:
case 0x9FA96F:
dx = -5;
break;
case 0xE5139CA7:
case 0xAC516266:
dy = 5;
break;
case 0xE4139B12:
case 0xAD5163FB:
dy = -5;
break;
case 0x21:
case 0x821:
dz = -5;
break;
case 0x20:
case 0x820:
dz = 5;
break;
case 0x11:
case 0x811:
dg = -5;
break;
case 0x10:
case 0x810:
dg = 5;
break;
case 0x1C102884:
case 0x4B995E59:
buttonRecord = !buttonRecord;
break;
case 0xC460AC26:
case 0x6626F67F:
buttonPlay = !buttonPlay;
break;
case 0xDF50BC53:
case 0xF04EE0E6:
repeatePlaying = !repeatePlaying;

if (repeatePlaying)
{
record = false;
play = true;
}
else
{
play = false;
}
break;
}
}
}
#endif

void setup() {
Serial.begin(9600);

pinMode(xdirPin, INPUT);
pinMode(ydirPin, INPUT);
pinMode(zdirPin, INPUT);
pinMode(gdirPin, INPUT);

pinMode(pinRecord, INPUT_PULLUP);
pinMode(pinPlay, INPUT_PULLUP);

pinMode(pinLedRecord, OUTPUT);

servoBase.attach(basePin);
servoShoulder.attach(shoulderPin);
servoElbow.attach(elbowPin);
servoGripper.attach(gripperPin);

StartPosition();

#if defined infraredSensor


irrecv.enableIRIn(); // Start the receiver
#endif

digitalWrite(pinLedRecord, HIGH);
delay(1000);
digitalWrite(pinLedRecord, LOW);
}

void loop() {
buttonRecord = digitalRead(pinRecord);
buttonPlay = digitalRead(pinPlay);
dx = 0;
dy = 0;
dz = 0;
dg = 0;

#if defined infraredSensor


CheckIrController();

if (debug)
{
Serial.println(results.value, HEX);
}

irrecv.resume(); // Receive the next value


#endif

// Serial.print(buttonRecord);
// Serial.print("\t");
// Serial.println(buttonPlay);
// for testing purposes

if (buttonPlay == LOW)
{
buttonPlayCount++;

if (buttonPlayCount >= buttonPlayDelay)


{
repeatePlaying = true;
}
}
else buttonPlayCount = 0;

if (buttonPlay != buttonPlayLast)
{
if (record)
{
record = false;
}

if (buttonPlay == LOW)
{
play = !play;
repeatePlaying = false;

if (play)
{
// StartPosition();
}
}
buttonPlayLast = buttonPlay;
}

if (buttonRecord != buttonRecordLast)
{
if (buttonRecord == LOW)
{
record = !record;

if (record)
{
play = false;
repeatePlaying = false;
recPos = 0;
cyclesRecord = 0;
}
else
{
if (debug) PrintBuffer();
}
}
buttonRecordLast = buttonRecord;
}

if (repeatePlaying)
{
play = true;
}

if (dx == 0) dx = map(analogRead(xdirPin), 0, 1023, 3.5, -3.5);


if (dy == 0) dy = map(analogRead(ydirPin), 0, 1023, 4.0, -4.0);
if (dz == 0) dz = map(analogRead(zdirPin), 0, 1023, 4.0, -4.0);
if (dg == 0) dg = map(analogRead(gdirPin), 0, 1023, -4.0, 4.0);

if (abs(dx) < 1.5) dx = 0;


if (abs(dy) < 1.5) dy = 0;
if (abs(dz) < 1.5) dz = 0;
if (abs(dg) < 1.5) dg = 0;

posBase += dx;
posShoulder += dy;
posElbow += dz;
posGripper += dg;

if ((play) | (cyclesPlay > 0))


{
if (cyclesPlay > 0)
{
cyclesPlay--;

if (cyclesPlay > 0)
{
if (play)
{
playPos = blockPlayPos;
}
else
{
play = false;
}
}
}

if (play)
{
if (playPos >= recPos)
{
playPos = 0;

if (repeatePlaying)
{
if (debug)
{
Serial.println("Auto start ");
}

delay(delayBetweenCycles);
// StartPosition();
}
else
{
play = false;
repeatePlaying = false;
}
}

blockPlayPos = playPos;
playBuffCount = 0;
bool endOfData = false;

while (!endOfData)
{
if (playPos >= buffSize - 1) break;
if (playPos >= recPos) break;

uint16_t data = buff[playPos];


byte angle = data & 0xFF;
uint16_t servoNumber = data & 0xf00;
endOfData = data & 0x8000;
uint16_t repeatCycles = data & 0x7000;
repeatCycles = repeatCycles >> 12;

if (play & cyclesPlay <= 0)


{
cyclesPlay = repeatCycles;
}

servoNumber = servoNumber >> 8;

playBuff[playBuffCount].ServoNumber = servoNumber;
playBuff[playBuffCount].Angle = angle;

playBuffCount++;

switch (servoNumber)
{
case 0:
posBase = angle;
break;

case 1:
posShoulder = angle;
break;

case 2:
posElbow = angle;
break;

case 3:
posGripper = angle;
dg = posGripper - lastGripper;
break;
}
// if (debug)
// {
// Serial.print("Play data ");
// Serial.print(data, BIN);
// Serial.print(" servo ");
// Serial.print(servoNumber);
// Serial.print(" angle ");
// Serial.print(angle);
// Serial.print(" end=");
// Serial.println(endOfData);
// }
//

playPos++;

if (playPos >= recPos)


{
play = false;

break;
}
}
}
}
else
{
cyclesPlay = 0;
}

if (posBase > maxBase) posBase = maxBase;


if (posShoulder > maxShoulder) posShoulder = maxShoulder;
if (posElbow > maxElbow) posElbow = maxElbow;
if (posGripper > maxGripper) posGripper = maxGripper;

if (posBase < minBase) posBase = minBase;


if (posShoulder < minShoulder) posShoulder = minShoulder;
if (posElbow < minElbow) posElbow = minElbow;
if (posGripper < minGripper) posGripper = minGripper;

bool waitGripper = false;


if (dg < 0) {
posGripper = minGripper;
waitGripper = true;
}
else if (dg > 0) {
posGripper = maxGripper;
waitGripper = true;
}

if (play && waitGripper)


{
delay(1000);
}

currentPos[0] = posBase;
currentPos[1] = posShoulder;
currentPos[2] = posElbow;
currentPos[3] = posGripper;

bool positionChanged = false;

if ((play) | (cyclesPlay > 0))


{
for (int i = 0; i < playBuffCount; i++)
{
MoveServo(servoPin[playBuff[i].ServoNumber], playBuff[i].Angle, servoTime);
}
}
else {
for (int i = 0; i < countServo; i++)
{
if (currentPos[i] > maxPos[i]) currentPos[i] = maxPos[i];
if (currentPos[i] < minPos[i]) currentPos[i] = minPos[i];

if (currentPos[i] != lastPos[i])
{
positionChanged = true;
MoveServo(servoPin[i], currentPos[i], servoTime);
}
}
}

if (positionChanged)
{
if (record)
{
buffPos = 0;
cyclesRecord = 0;

for (int i = 0; i < countServo; i++)


{
if (lastPos[i] != currentPos[i])
{
uint16_t value = (currentPos[i] | (0x100 * i)) & 0x0FFF;
buffAdd[buffPos] = value;
buffPos++;
}
}
buffAdd[buffPos - 1] = buffAdd[buffPos - 1] | 0x8000;

AddToBuff();
}
}
else
{
if (record)
{
if (recPos > 0)
{
cyclesRecord ++;

bool added = false;


bool first = true;

for (int i = recPos - 1; i >= 0; i--)


{
bool endOfData = buff[i] & 0x8000;

if (!first && endOfData) break;

if (cyclesRecord > 7)
{
cyclesRecord = 0;

AddToBuff();
added = true;
}

if (!added) {
uint16_t val = cyclesRecord & 7;
val = val << 12;
val = val & 0x7000;

buff[i] = buff[i] & 0x8FFF;


buff[i] = buff[i] | val;

// if (debug)
// {
// Serial.print(" i=");
// Serial.print(i);
// Serial.print(" Buff[i]=");
// Serial.print(buff[i], BIN);
// Serial.print(" val=");
// Serial.println(val, BIN);
// }

first = false;
}
}
}
}
}

lastBase = posBase;
lastShoulder = posShoulder;
lastElbow = posElbow;
lastGripper = posGripper;

for (int i = 0; i < countServo; i++)


{
lastPos[i] = currentPos[i];
}

if ( repeatePlaying)
{
ledLight = !ledLight;
}
else
{
if (ledLight)
{
ledLight = false;
}

if (record)
{
ledLight = true;
}
};

digitalWrite(pinLedRecord, ledLight);
delay(50);
}
void AddToBuff()
{
for (int i = 0; i < buffPos; i++)
{
buff[recPos + i] = buffAdd[i];
}

recPos += buffPos;

if (recPos >= buffSize - countServo)


{
record = false;
}
}

void MoveServo(uint8_t idServo, int angle, int timeMs)


{
switch (idServo)
{
case basePin:
servoBase.write(angle);
break;
case shoulderPin:
servoShoulder.write(angle);
break;
case elbowPin:
servoElbow.write(angle);
break;
case gripperPin:
servoGripper.write(angle);
break;
}

if (debug)
{
if (record) Serial.print(" Record ");
if (play) Serial.print(" Play ");
if (repeatePlaying) Serial.print(" Auto ");

Serial.print(" Servo ");


Serial.print(idServo);
Serial.print(" Angle ");
Serial.println(angle);
}
}
void PrintBuffer()
{
for (int i = 0; i < recPos; i++)
{
uint16_t data = buff[i];
byte angle = data & 0xFF;
uint16_t servoNumber = data & 0xF00;
servoNumber = servoNumber >> 8;
bool endOfData = data & 0x8000;

Serial.print("Servo=");
Serial.print(servoNumber, HEX);
Serial.print("\tAngle=");
Serial.print(angle);
Serial.print("\tEnd=");
Serial.print(endOfData);
Serial.print("\tData=");
Serial.print(data, BIN);
Serial.println();
}
}

void StartPosition()
{
int angleBase = servoBase.read();
int angleShoulder = servoShoulder.read();
int angleElbow = servoElbow.read();
int angleGripper = servoGripper.read();

Serial.print(angleBase);
Serial.print("\t");
Serial.print(angleShoulder);
Serial.print("\t");
Serial.print(angleElbow);
Serial.print("\t");
Serial.print(angleGripper);
Serial.println("\t");

posBase = startBase;
posShoulder = startShoulder;
posElbow = startElbow;
posGripper = startGripper;

servoBase.write(posBase);
servoShoulder.write(posShoulder);
servoElbow.write(posElbow);
servoGripper.write(posGripper);
}

138) Arduino Air Meter Making Projet

COMPONENTS AND SUPPLIES


Arduino Nano R3

× 1
DHT11 Temperature & Humidity Sensor (4
pins)
× 1

Espressif ESP8266 ESP-01

× 1

Aduino fine dust sensor (PPD42NS)


× 1
Co2 sensor v1.2
× 1
Rotary potentiometer (generic)

× 1

20x4 lcd

ABOUT THIS PROJECT


I have rhinitis so I wanted to know the air quality level of our school.
So I decided to make a device that can measure air quality and I wanted
to make this information available on the Internet in real time. So I
tried to google how to do this and in the end I concluded that it would
be best to use the sites called "Arduino" and "thingspeak".
After making these conclusions, I thought about what functions to
include in the Air Meter I produce, and concluded that temperature,
humidity, fine dust, and CO2 concentration, which have a large impact
on air quality, must be made measurable. And I started by looking for
information on the Internet. We could combine the examples collected
from the Internet with each other, and eventually create the code that
performs the desired action. Of course, it was not easy.
Issues
I spent a lot of time and effort trying to figure out how the middle code
example works. Also the ESP8266 WiFi module was unstable and this
bothered me. The accuracy of the fine dust sensor I bought at first (Air
Meter v1.5) was very low, the fine dust sensor was also scratched and
the CO2 sensor used too much electric power to supply additional
external power.
Air Meter prototype ↓ (Function: Temperature and humidity
measurement)
Air Meter v1.0 ↓ (Function: Temperature, humidity, fine dust
measurement)
Air Meter v1.5 ↓ (Function: temperature, humidity, fine dust, co2
concentration measurement + fine dust sensor change)
Air Meter v2.0 ↓ (Same as Air Meter v1.5 with some minor fixes)
SCHEMATICS
CODE
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include <stdlib.h>
#include <DHT.h>

boolean state_led1 = 0;
const int duration2 = 16000;

#define MG_PIN (0) //define which analog input channel you are
going to use
#define BOOL_PIN (2)
#define DC_GAIN (8.5) //define the DC gain of amplifier
#define READ_SAMPLE_INTERVAL (50) //define how many samples you are
going to take in normal operation
#define READ_SAMPLE_TIMES (5) //define the time interval(in
milisecond) between each samples in
//normal operation
#define ZERO_POINT_VOLTAGE (0.37) //define the output of the sensor in
volts when the concentration of CO2 is 400PPM
#define REACTION_VOLTGAE (0.020) //define the voltage drop of the
sensor when move the sensor from air into 1000ppm CO2
float CO2Curve[3] = {2.602,ZERO_POINT_VOLTAGE,
(REACTION_VOLTGAE/(2.602-3))};

#define DHTPIN 4 // Setting the SDA pin


#define DHTTYPE DHT11 // DHT22 (AM2302) Sensor type setting
int pin = 3; //Dust sensor
unsigned long duration; //duration
unsigned long starttime; //Start time
unsigned long sampletime_ms = 30000; //Updated every 30 seconds of sample time
unsigned long lowpulseoccupancy = 0; //Low Initializes the time the signal lasted
float ratio = 0; //ratio
float concentration = 0; //Initialized to zero particle concentration
float pcsPerCF = 0; //Initialize CF to 0 per particle
float ugm3 = 0; //The final value, in micrograms per cubic meter(㎍/㎥)

unsigned long pre_time = 0;


unsigned long cur_time = 0;

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);


// Upload Notification LED Setting (Adunono On Board LED)
int ledPin = 13;

// Enter Write API key for your own thingspeak channel


String apiKey = "Your API Key";

SoftwareSerial ser(6,5 ); //RX / TX configuration, serial object creation


DHT dht(DHTPIN, DHTTYPE);

void setup() {
pre_time = millis();
pinMode(3,INPUT);
pinMode(4,INPUT);
pinMode(BOOL_PIN, INPUT); //set pin to input
digitalWrite(BOOL_PIN, HIGH); //turn on pullup resistors
lcd.begin(20, 4);
dht.begin();
//Notification LED Output Settings
pinMode(ledPin, OUTPUT);
//Serial communication speed 9600 baud rate setting
Serial.begin(9600);
//Start the software serial
ser.begin(9600);
//ESP8266 Reset
ser.println("AT+RST");
}

void loop() {
delay(1800);
cur_time = millis();//Assign millis to cur_time (for parallel operations)
int percentage;
float volts;
Serial.println( pre_time );
Serial.println( cur_time);

//co2 Measurement Codes--------------------------------------------------------


volts = MGRead(MG_PIN);
Serial.print( "SEN-00007:" );
Serial.print(volts);
Serial.print( "V " );
Serial.println(volts/DC_GAIN);

percentage = MGGetPercentage(volts,CO2Curve);

Serial.print("CO2:");
if (percentage == -1) {
Serial.print( "<400" );
} else {
Serial.print(percentage);
}

Serial.print( "ppm" );
Serial.print("\n");

if (digitalRead(BOOL_PIN) ){
Serial.print( "=====BOOL is HIGH======" );
} else {
Serial.print( "=====BOOL is LOW======" );
}

Serial.print("\n");
//---------------------------------------------------------------------------

//Fine dust measuring section code-------------------------------------------

duration = pulseIn(pin, LOW);


lowpulseoccupancy = lowpulseoccupancy+duration;

if ((millis()-starttime) >= sampletime_ms) { //If the sample time is 5 seconds (the sample
time specified above)
ratio = lowpulseoccupancy/(sampletime_ms*10.0); // Integer percent
concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // Fine dust sensor
specification Sheet curve use
pcsPerCF = concentration * 100; // When the particle concentration is multiplied by 100,
the CF value per particle
ugm3 = pcsPerCF / 13000; //When CF per particle is divided by 13000, the fine dust
measurement of micrograms per cubic meter
Serial.print(ugm3);
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print("Dust:");
lcd.setCursor(6, 2);
lcd.print(ugm3);
lcd.print("ug/m3");
lowpulseoccupancy = 0;
starttime = millis();
}

// blink LED on board


digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);

//Read DHT11 value


float temp = dht.readTemperature();
float humi = dht.readHumidity();

// String Conversion
char buf[16];
String strTemp = dtostrf(temp, 4, 1, buf);
String strHumi = dtostrf(humi, 4, 1, buf);

Serial.println(strTemp);
Serial.println(strHumi);
Serial.print("Dust density(ug/m3) = ");
Serial.println(ugm3);
//Measured value lcd display section------------------------------------------

lcd.setCursor(0, 3);
lcd.print(" ");
lcd.setCursor(0, 3);
lcd.print("Co2:");
if (percentage == -1) {
lcd.print( "<400" );
} else {
lcd.print(percentage);
lcd.print("ppm");
}

lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Temperature:");
lcd.setCursor(13, 0);
lcd.print(strTemp);
lcd.setCursor(0, 1);
lcd.print("Humidity:");
lcd.setCursor(10, 1);
lcd.print(strHumi);

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

if(cur_time - pre_time >= duration2){//Sensor measurement and measurement lcd


Independent from the display section Transfer measurements to the thingspeak server once
every 16 seconds

pre_time = cur_time;

// TCP connection
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += "184.106.153.149"; // api.thingspeak.com Access IP
cmd += "\",80"; // api.thingspeak.com access port, 80
ser.println(cmd);

if(ser.find("Error")){
Serial.println("AT+CIPSTART error");
lcd.setCursor(13, 3);
lcd.print("Wifioff");
return;
}

// Set String, Data to send by GET method


String getStr = "GET /update?api_key=";
getStr += apiKey;
getStr +="&field1=";
getStr += String(strTemp);
getStr +="&field2=";
getStr += String(strHumi);
getStr +="&field3=";
getStr += String(ugm3);
getStr +="&field4=";
getStr += String(percentage);
getStr += "\r\n\r\n";

// Send Data
cmd = "AT+CIPSEND=";
cmd += String(getStr.length());
ser.println(cmd);

if(ser.find(">")){
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<READ_SAMPLE_TIMES;i++) {
v += analogRead(mg_pin);
delay(READ_SAMPLE_INTERVAL);
}
v = (v/READ_SAMPLE_TIMES) *5/1024 ;
return v;
}

int MGGetPercentage(float volts, float *pcurve)


{
if ((volts/DC_GAIN )>=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

× 1

Adafruit NeoPixel LED Strip


Starter Pack - 30 LED meter × 4

SparkFun Piezo element


× 4
Resistor 220 ohm
× 4

SparkFun Resistor 1M ohm


× 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<LED_TYPE, 2, COLOR_ORDER>(leds[0],
NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);

FastLED.addLeds<LED_TYPE, 3, COLOR_ORDER>(leds[1],
NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);

FastLED.addLeds<LED_TYPE, 4, COLOR_ORDER>(leds[2],
NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, 5, COLOR_ORDER>(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 <FastLED.h>

#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<LED_TYPE, 2, COLOR_ORDER>(leds[0],
NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, 3, COLOR_ORDER>(leds[1],
NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, 4, COLOR_ORDER>(leds[2],
NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, 5, COLOR_ORDER>(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

× 1

Adafruit display nokia 5110


× 1

Jumper wires (generic)

× 1
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 <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

// 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()-UtlTime<0)
{
UtlTime=millis();
}
else
{
second=int((millis()-UtlTime)/1000);
}
if(second>59)
{
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

× 1

Ultrasonic Sensor - HC-SR04


(Generic)
× 1

passive buzzer module


U can find it on ali express, it × 1
costs less than a dollar.
HC-06 Bluetooth Module
× 1

LED (generic)

× 1

Male/Female Jumper Wires

× 1
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; // buzzzer signal pin attached to digital pin 8


const int trigPin = 11; // 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); // initiate the ultrasonic sensor for sending and
receiving
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

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: "); // print distance (meters) in serial monitor


Serial.print(distanceMeters);
Serial.println(" Meters");
delay(300);

Serial.print("Distance: "); // print distance (centi meters) in serial monitor


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

Serial.print("Distance: "); // print distance (inches) in serial monitor


Serial.print(distanceInch);
Serial.println(" inch");
delay(300);
Serial.println("----------------------------"); // seoeration

if (distanceCm <= 30 ) { // if distance is greater than or equal to 30 cm on


LED and on buzzer ON and OFF
digitalWrite(13, HIGH); // ...... with delay as interval
tone(buzzerPin, 1200);
delay(500); // u can tweak the code to suit yourn needs
noTone(buzzerPin);
digitalWrite(13, LOW);
delay(5);
}
else if (distanceCm > 100 ) {
digitalWrite(13, LOW);
noTone(buzzerPin);
}
}

142) Arduino Music Player Projet


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Generic 16x2 LCD


× 1

Generic IR Receiver
× 1

Resistor 221 ohm


× 2

Buzzer

× 1

General Purpose Transistor NPN


S8050
× 1

Rotary potentiometer (generic)

× 1

Jumper wires (generic)

× 23

Solderless Breadboard Full Size

× 1
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 <IRremote.h>
#include <LiquidCrystal.h>
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 <IRremote.h>
#include <LiquidCrystal.h>
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

× 1

10 mega ohm resistor


× 1

LED (generic)

× 1

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.h>
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);
}
}
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.h>

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
× 1

Elegoo 2.8 inch TFT LCD Shield


× 1

Rotary potentiometer (generic)


× 2

Solderless Breadboard Half Size

× 1
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; // TODO - Colour of Graph
Outline
uint16_t blockColor = GREEN; // TODO - Colour of Bars
String graphName = "3D Bar Chart"; // 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 <Elegoo_GFX.h> // Core graphics library


#include <Elegoo_TFTLCD.h> // 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; // 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; // TODO - Colour of Graph Outline


uint16_t blockColor = GREEN; // TODO - Colour of Bars

String graphName = "3D Bar Chart"; // 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

// 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

Jumper wires (generic)

× 1
Arduino UNO & Genuino UNO

× 1

Breadboard (generic)

× 1

Buzzer

× 1

Resistor 10k ohm

× 2

Resistor 1M ohm

× 1

Resistor 221 ohm

× 1
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<MAX_COUNT1; i++) { //Set up a counter to pull from melody1[] and
beats1[]
tone_ = melody1[i]; //Defining which notes to play
beat = beats1[i]; //Defining the note lengths to use
duration = beat * tempo; //Set up timing
playTone(); //Inserting/applying the code for a pause between notes
delayMicroseconds(pause);
}
}
// PIN TWO (ALL STAR)
else if(keyVal >= 990 && keyVal <= 1010){ //Only when the 2nd button is pressed
for (int i=0; i<MAX_COUNT2; i++) { //Set up a counter to pull from melody2[] and
beats2[]
tone_ = melody2[i]; //Defining which notes to play
beat = beats2[i]; //Defining the note lengths to use
duration = beat * tempo; //Set up timing
playTone(); //Inserting/applying the code for a pause between notes
delayMicroseconds(pause);
}
}
// PIN THREE (JEOPARDY)
else if(keyVal >= 480 && keyVal <= 515){ //Only when the 3rd button is pressed
for (int i=0; i<MAX_COUNT3; i++) { //Set up a counter to pull from melody3[] and
beats3[]
tone_ = melody3[i]; //Defining which notes to play
beat = beats3[i]; //Defining the note lengths to use
duration = beat * tempo; //Set up timing
playTone(); //Inserting/applying the code for a pause between notes
delayMicroseconds(pause);
}
}
// PIN FOUR (LONELY)
else if(keyVal >= 5 && keyVal <= 10){ //Only when the 4th button is pressed
for (int i=0; i<MAX_COUNT4; i++) { //Set up a counter to pull from melody4[] and
beats4[]
tone_ = melody4[i]; //Defining which notes to play
beat = beats4[i]; //Defining the note lengths to use
duration = beat * tempo; //Set up timing
playTone(); //Inserting/applying the code for a pause between notes
delayMicroseconds(pause);
}
}
// NONE
else{
noTone(8);
}
}
146) Arduino DC Motor Speed Control and Measurement Projet
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Geared DC Motor, 12 V

× 1

Alphanumeric LCD, 20 x 4

× 1
Darlington High Power Transistor

× 1
NECESSARY TOOLS AND MACHINES
Breadboard, 270 Pin
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


In DC motor speed testing, the PWM is applied to motor and its duty
cycle is varied from min to max. While applying PWM the actual RPM
of DC motor is also measured and note down to see how motor speed
(RPM) varies as PWM width varies. Along with this, the applied
voltage to motor is also measured to see the motor speed at different
applied voltage. Finely, after noting down all the values, the
observation table is prepared for pulse width (duty cycle), applied
voltage and motor speed in RPM. This table is used to prepare duty
cycle->RPM graph or applied voltage->RPM graph of motor.
The given project demonstrates above example. It applies PWM to DC
motor to vary its speed from min to max and max to min continuously
and also measures following parameters
1) PWM width in %
2) Applied voltage to motor
3) Motor speed in RPM
It uses arduino UNO board to generate PWM and measure/calculate
above 3 parameters. These parameters are displayed on 16x4 LCD. It is
very easy to vary speed of DC motor using arduino. Arduino can
generate PWM on its analog output pin and when it is applied to DC
motor, its speed varies. So it is very simple and easy task. To measure
RPM, opto-interrupt sensor MOC7811 is used. When motor completes
1 revolution, the sensor generates 1 pulse and such pulses are
calculated by arduino to calculate RPM. So let us see how this is done.
Lets start with circuit diagram first, followed by its descriptions and
operation.
Circuit diagram:

Circuit description:
As shown in figure, the circuit is built using arduino UNO development
board, 16x4 LCD, NPN Darlington transistor TIP122 and opto interrupt
sensor MOC7811.
· The analog output pin 9 of arduino drives 12V@2000 RPM DC motor
through TIP122. This pin is given to base input of TIP122 through
current limiting resistor R2 and DC motor is connected to collector of
TIP122
· The internal IR LED of MOC7811 is given forward bias using 5V
supply form arduino board through current limiting resistor R1.
Internal photo transistor is pulled up by resistor R4. The collector
output of transistor is connected to digital pin 7 or arduino
· LCD data pins D4 to D7 are connected to digital pins 5, 4, 3 and 2 of
arduino while control pins Rs and En are connected to 12 and 11. RW
pin is connected to ground. Vcc pin and LED+ pin are connected to 5V
supply from arduino board and Vss pin and LED- pins are connected to
arduino board ground
· One pot is connected to Vee pin to vary contras of LCD
Circuit operation:
· First the motor is given 12 V supply through external power supply.
Next the arduino board, LCD and sensor is given supply through USB
from PC / laptop
· Initially the LCD shows different parameters as
PWM ip:
PWM Duty:
PWM volt:
speed:
· Then arduino starts applying PWM to motor with maximum pulse
width
· So motor will start rotating at maximum speed. Some time delay is
provided to allow motor to attain full speed
· As the motor starts rotating, the slotted wheel attached to its shaft will
also rotate
· The MOC7811 sensor is placed such a way that the slot of wheel
passes through sensor air gap. Thus when motor rotates one full
revolution, the slot passes through sensor gap. Due the slot in the wheel
the IR light falls on photo transistor. So transistor conducts and
generates negative pulse in collector output. Thus each rotation of
motor produces pulse
· The frequency of these pulses is actually RPS (-revolution per
second) of motor. To measure the frequency of this pulse first the ON
time is measured then OFF time is measured and from these frequency
is calculated as
Time period = Ton + Toff (in us)
Frequency= 1000000/time period
· This frequency is speed of motor in RPS. From this RPS, speed of
motor is calculated in RPM as
RPM= 60×RPS
· The PWM input is varied from 250 to 100 in step of 15. That is
directly displayed on LCD
· The ON time and OFF time of PWM output is also measured to
calculate the PWM duty cycle as
PWM duty = [PWM_Ton / (PWM_Ton + PWM_Toff)] × 100
· Finally voltage applied to motor is calculate as
Voltage applied to motor = motor voltage × duty
= (12/100)× duty
· First the PWM input is decreased from 250 to 100 in 10 steps of 15
and then again it is increased from 100 to 250 and this cycle is repeated
continuously
· So motor speed continuously decreases and then continuously
increases. We can observe the change in motor speed that is displayed
on LCD as speed in RPM
Thus the given project varies the speed of DC motor and also measures
it accurately. It displays % of pulse width applied to motor along with
applied voltage. So one can note down motor speed in RPM at different
voltage and pulse width in observation table for further needs.

SCHEMATICS
CODE
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 10, 11, 12, 13);


#define motor_RPS_pulse_ip 7
#define motor_PWM_pulse_ip 4
int motor_RPS_Ton,motor_RPS_Toff,PWM_Ton,PWM_Toff,PWM_T;
int PWM_duty,pulse_width=255,RPS,motor_RPS_period,RPM;
float voltage;

void setup()
{
pinMode(motor_RPS_pulse_ip,INPUT);
pinMode(motor_PWM_pulse_ip,INPUT);
lcd.begin(16, 4);
lcd.clear();
lcd.print("Pulse Width:");
lcd.setCursor(0,1);
lcd.print("PWM Volt:");
lcd.setCursor(0,2);
lcd.print("Speed(RPS):");
lcd.setCursor(0,3);
lcd.print("Speed(RPM):");
}
void loop()
{
analogWrite(3,pulse_width);
PWM_Ton= pulseIn(motor_PWM_pulse_ip,HIGH);
PWM_Toff=pulseIn(motor_PWM_pulse_ip,LOW);
delay(2000);
PWM_T = PWM_Ton+PWM_Toff;
PWM_duty = (PWM_Ton/PWM_T)*100;
voltage = 0.12*PWM_duty;
lcd.setCursor(12,0);
lcd.print(PWM_duty);
lcd.print('%');
lcd.setCursor(9,1);
lcd.print(voltage);
lcd.print('V');
pulse_width-=15;
if(pulse_width==90) pulse_width = 255;
delay(3000);
}

147) Sending Data from PC To Another using Arduino Projet

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 2
433MHZ RF wireless receiver &
transmitter module × 1

Adafruit RGB Backlight LCD -


16x2
× 2

Breadboard (generic)

× 2

Rotary potentiometer (generic)


10K Ohm is fine.
× 2
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


This project is a good tutorial on sending data using Cheap RF module
without dumping the data.
I need to send some data form my laptop serial monitor (embedded tool
with arduino IDE) to my PC and receive the data on Arduino IDE serial
monitor, so we need:
* Arduino Uno attached to laptop and another for the PC.
Laptop Uno connected to the RF transmitter part and the PC Uno
connected to the Receiver.
* each arduino connected to a text LCD to display the sent data as
stars, ex(******) -- this step is not important ,just for fun :D.
Steps :
1 - Connect all the parts as Schematics below.
2 - Starting with the Laptop Uno [the Transmitter]:
Setup and initialize your serial communications.
Read the User input data from serial monitor then.
Reading and sending data from serial port (USB) with arduino is "a
piece of cake" compared with the same task using PIC 18F2550, I will
post soon how to build that project using 18F2550 MCU, it will make
you pull out your hair :D.
Send it to PC Uno [the Receiver] through the RF module , consider
how "Virtual wire" library works.
3 - Display the data encrypted on the LCD "Optional"
4 - The code source is down below.
then we go to the PC Uno [the Receiver]:
- Read the received data from RF receiver then, write it to serial port to
display it on the serial monitor.

SCHEMATICS
Laptop Uno connected to RF transmitter

PC Uno connected to RF Receiver


CODE
Transmitter.ino

#include <VirtualWire.h>
#include <VirtualWire_Config.h>

#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

char cad[100];
int i=0;
void setup()
{
// put your setup code here, to run once:
lcd.begin(16, 2);
lcd.setCursor(3, 0);
lcd.print("UNO-TX !");

// initialize serial:
Serial.begin(9600);
vw_setup(2000);
Serial.println("Encrtypted Communication");
Serial.println("Developed by: Mr-Joe");
Serial.println("-------------------------");
Serial.println("Important:(UNO - TX) ");
Serial.println("End with \".\" each data");
}
void loop()
{
if( Serial.available() > 0)
{
cad[i] = Serial.read();
i++;
}
if( cad[i-1] == '.')
{
lcd.setCursor(1, 1);
lcd.print( "**Classified** " );

cad[i] = '\0';
i=0;
vw_send((byte *)cad, strlen(cad));
delay(400);
}
}
Receiver.ino

#include <VirtualWire.h>
#include <VirtualWire_Config.h>

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);


char cad[100];
int pos = 0;
void setup()
{
// put your setup code here, to run once:
lcd.begin(16, 2);
lcd.setCursor(3, 0);
lcd.print("UNO-RX !");

// initialize serial:
Serial.begin(9600);
vw_setup(2000);
Serial.println("Encrtypted Communication");
Serial.println("Developed by: Mr-Joe ");
Serial.println("-------------------------");
Serial.println("Important:(UNO - RX) ");

// initialize Virtual wire :


vw_setup(2000);
vw_rx_start();
}

void loop()
{
byte buf[VW_MAX_MESSAGE_LEN];
byte buflen = VW_MAX_MESSAGE_LEN;
int i;
if( vw_get_message(buf, &buflen) )
{
// dont uncomment that unless you need to use a flag for each received
line.
/*if(pos < 2)
lcd.setCursor(0, 1);
else
{
pos=0;
Serial.println(" ");
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("UNO-RX !");
lcd.setCursor(1, 1);
}*/

for (i = 1; i < buflen; i++)


{
Serial.print((char)buf[i]);

}
if( buf[i-1] == '.')
{
lcd.setCursor(1, 1);
lcd.print( "**Classified** " );
Serial.println(" ");

buf[i] = '\0';
i=0;
}
}
}
148) Arduino Burglar Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO
×1

LED (generic)

×1

LED (generic)

×1

LED (generic)

×1

Buzzer

×1

Adafruit keypad
×1

Breadboard (generic)

×1

Adafruit lcd i2c


×1

Resistor 1k ohm
×1

Resistor 1k ohm

×1

Resistor 1k ohm

ABOUT THIS PROJECT


INTRODUCTION
The following project had the purpose to be a burglar made with an
Arduino UNO shield and some sensor.
DESCRIPTION OF THE ASSIGNMENT
The project made by Cravero and Zanella become to the request to
produce a thing that could be functional and useful.
TOOLS AND MATERIALS
To produce this burglar, the components are:
An HC-SR501 sensor pir;
An Arduino UNO;
A Led;
An LCD screen16X2;
Membrane switch.r;
Membrane swtch.
For the case of the burglar has been used a box
Arduino UNO
HC-SR501 pir sensor
lcd16X2 screen
Active buzzer
Membrane switch
LED green, blue, and red
EXECUTION
To product this project it was necessary the following schedule
1. Research for the component;
2. Implementation of the program;
3. Creation of the box
4. Test of the burglar;
5. Assembly;
6. Report.
SOLUTION ADOPTED
The project is made by a sensor pir hc-sr501, linked with an active
buzzer, which had the function of acoustic burglar, one or more LED
with the function of visive burglar, a membrane switch which is used
like a keypad to enable and disable the burglar and finally an LCD 1X2
screen that is used to send some messages to the user.
WORKING
The working of the burglar is divided into 3 cases:
CASE 0: It’s the first case, it is used to turn on the burglar by the input
of a pin, (9856), that state is marked with a green LED.
CASE 1: This state is used to disable the burglar by pushing a key (D),
or if the pir detect a motion this state turn on the burglar, this state is
marked with blue LED.
Case 2: This state is the burglar alarm, this state will turn on the buzzer
and a led red to signal an intrusion.
SCHEMATICS

CODE
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5,
d6, d7, backlighpin, polarity
#include <Keypad.h> //includo libreria per tastierino numerico 4*4
#define led 10
#define led1 13
#define led2 12
#define PIR 7
#define BUZZER 6

const byte dim = 4;


char tastiera[dim][dim] =

{
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
}; //matrice che rappresenta la tastiera collegata ad arduino
byte pinRiga[dim] = {19, 15, 16, 17};
byte pinColonna[dim] = {1, 2, 3, 4}; //vettore che contiene i pin delle colonne
//vettore che contiene i pin delle righe
char tasto; //variabile che contiene il valore del tasto premuto
bool Pass_Completa = false ;

#define Lunghezza_Password 5 //costante che identifica la lunghezza della password = 4


cifre + '\0' --> ( '\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<4;i++)
password[i] = NULL;

Pass_Completa = false; //imposto nuovamente false

delay(3000); //ritardo di un secondo

digitalWrite(led1,LOW);
break; //end case 0

/*Stato in cui è attivo rilevatore di momvimento (PIR)*/


case 1:
digitalWrite(led2,HIGH);
lcd.clear();
tasto = 0; //il contenuto di tasto è nullo

lcd.println("Antifurto ON");
delay(3000);
lcd.clear();
lcd.println("Tasto D per OFF");
//delay(3000);

while(AllarmeAttivo == true)
{
tasto = keypad.getKey(); //lettura tasto premuto
keypad.setDebounceTime(tempo); //debounce per tasto premuto

valPIR = digitalRead(PIR);

lcd.clear();
#if DEBUG
lcd.clear();
lcd.println(tasto);
delay(1000);
lcd.clear();
delay(10);
#endif

if(valPIR == 1)
{ digitalWrite(led2, LOW);
stato = 2;
AllarmeAttivo = false; //imposto il valore a falso
}

if(tasto == 'D')
{ digitalWrite(led2, LOW);
lcd.clear();
lcd.println("disattivazione");
stato = 0; //imposto lo stato a 0 per tornare così allo stato di partenza

AllarmeAttivo = false; //imposto il valore a falso


delay(3000);
lcd.clear();

} //end if

} //end while

AllarmeAttivo = true; //reimposto valore iniziale di AllarmeAttivo

break; //end case 1

case 2:

for(int c = 0; c < 3; c++)

{
analogWrite(BUZZER,HIGH);
digitalWrite(led, HIGH);
delay(500);
analogWrite(BUZZER,LOW);
digitalWrite(led, LOW);
delay(500);
}

stato = 1;
break;

149) Home Automation using Arduino and Sheeld Projet


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

1Sheeld

× 1

Jumper wires (generic)


× 1

Breadboard (generic)

× 1

Android device

× 1

Arduino cable
× 1

electric strike
× 1

relay module
× 1

smoke sensor module


× 1

jumpers
× 1

lamp
× 1
ABOUT THIS PROJECT
This project enables you to:
1. Control your home (or at least your room's) lights and power outlets
(on/off) using a keypad in your android smartphone.
2. Get a buzzer beep through your phone speaker in case of detecting
smoke in your home that exceed a threshold predefined value.
3. Access your home, simply opening your home door lock, through
entering a pattern. In case of entering the correct pattern, the door becomes
unlocked and you get an email informing you that the home was accessed.
In case of entering a wrong pattern, a photo of the one entering the pattern
is captured and sent to you attached in a mail informing you of an attempt
to access the home.
First Step:
1. Connect the 1sheeld to the arduino.
2. Connect the signal pin of the relay module to pin 13 in the Arduino.
3. Connect the vcc pin of the relay module to the 5V pin of the Arduino.
4. Connect the GND pin of the really module to pin GND of the Arduino.
5. Connect the vcc pin of the smoke sensor to pin 5V of the Arduino.
6. Connect the GND pin of the smoke sensor to the GND pin of the
arduino.
7. Connect the analog signal pin of the smoke sensor to pin A0 of the
Arduino.
8. Connect the signal pin of the electric strike to pin 13 of the Arduino.
9. Connect the power pins of the electric strike to prop-er power sources.
10, Connect Arduino to your computer through the USB cable.
Connection of arduino, 1sheeld and the modules
Second Step: Write the code
1. Download 1sheeld Arduino Library and save it in the suitable folder.
2. Start writing the code by adding initialization values and library
defining
#define CUSTOM_SETTINGS
#define INCLUDE_BUZZER_SHIELD
#define INCLUDE_PUSH_BUTTON_SHIELD
#define INCLUDE_KEYPAD_SHIELD
#define INCLUDE_EMAIL_SHIELD
#define INCLUDE_PATTERN_SHIELD
#define INCLUDE_CAMERA_SHIELD
#include
int taken =0;
long previousMillis = 0;
int State = LOW;
int lamp = 12;
int sensor = A0;
int reading = 0;
int Lock = 13;
PatternNode patternStored[] = { {0, 0}, {1, 0}, {2, 0}, {2, 1}, {2, 2} };
int counter = 0;
int length = 0;
3. Writing the setup part of the arduino program
void setup()
{
OneSheeld.begin();
pinMode(lamp, OUTPUT);
pinMode(sensor, INPUT);
pinMode(Lock, OUTPUT);
}
4. Write the function of the pattern and door lock
void pattern() { if (Pattern.isNewPatternReceived())
{
/* This pointer act as array to store the last pattern entered by user. */
PatternNode * patternEntered = Pattern.getLastPattern();
/* Get the length of the pattern to loop over it. */
length = Pattern.getLastPatternLength();
/* Check if the pattern length is equal to 5. */
if (length == 5)
{
for (int i = 0; i < length ; i++)
{
if (patternEntered[i].row == patternStored[i].row && patternEntered[i].col
== patternStored[i].col)
{
counter++;
}
}
if (counter == 5)
{
digitalWrite(Lock, HIGH); // lock is high when opened
Email.send("[email protected]", "Your Home Security", "Your
home was accessed right now!");
taken =0;
}
else
{
digitalWrite(Lock, LOW);
if (taken ==0){
Camera.setFlash(ON);
Camera.rearCapture();
taken = 1;
}
Email.attachLastPicture ("[email protected]", "Your Home
Security", "Someone tried to access your home and we took a picture of
him", 0);
counter = 0;
}
}
/* If pattern length is different turn off the LED. */
else
{
digitalWrite(Lock, LOW);
if (taken ==0){
Camera.setFlash(ON);
Camera.rearCapture();
taken = 1;
}
Email.attachLastPicture ("[email protected]", "Your Home
Security", "Someone tried to access your home and we took a picture of
him", 0);
}
}
}
5. Write the loop part of the code in which the function of the keypad and
the smoke sensor and the calling of the pattern function are included
void loop()
{
if (Keypad.isRowPressed(0) && Keypad.isColumnPressed(0))
{
if (digitalRead(lamp) == LOW)
{
digitalWrite(lamp, HIGH);
}
else
{
digitalWrite(lamp, LOW);
}
}
reading = analogRead(sensor);
if (reading >= 90) {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > 1500) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (State == LOW)
{ State = HIGH;
Buzzer.buzzOn();
}
else
{ State = LOW;
Buzzer.buzzOff();
}
}
}
else
{
Buzzer.buzzOff();
}
pattern();
}
Third step: Upload the code
1. Switch the 1sheeld to the upload mode with the switch being directed
away from 1sheeld logo.
2. Verify the code on Arduino IDE.
3. Upload the code to the Arduino.
4. Switch the 1sheeld to the bluetooth mode using the switch directed
towards the 1sheeld logo.
Fourth and Final Step: HAVE FUN!
1. Download 1sheeld app from play store for android.
2. Open your bluetooth and connect to your shield from the app.
3. Add the following shields:
- Buzzer
- Keypad
- E-mail
- Camera
- Pattern
4. Start testing:
- Click the '1' button of the keypad and enjoy the lamp turning on and
turning off when you click it again.
- Expose the smoke sensor of your home to smoke and listen to your
phone speaker beeping.
- Try to enter the correct pattern (which is L in this case as written in the
code and which is the default pattern) and see the electric strike opening
and receiving the email.
- Try to enter a wrong pattern and check the received mail with your photo
attachedas the one who have tried to access the home door.
SCHEMATICS

CODE
#define CUSTOM_SETTINGS
#define INCLUDE_BUZZER_SHIELD
#define INCLUDE_KEYPAD_SHIELD
#define INCLUDE_EMAIL_SHIELD
#define INCLUDE_PATTERN_SHIELD
#define INCLUDE_CAMERA_SHIELD
#include <OneSheeld.h>
int taken =0;
long previousMillis = 0;
int State = LOW;

int lamp = 12;


int sensor = A0;
int reading = 0;
int Lock = 13;
PatternNode patternStored[] = { {0, 0}, {1, 0}, {2, 0}, {2, 1}, {2, 2} };
int counter = 0;
int length = 0;

void setup()
{
OneSheeld.begin();
pinMode(lamp, OUTPUT);
pinMode(sensor, INPUT);
pinMode(Lock, OUTPUT);

void loop()
{
if (Keypad.isRowPressed(0) && Keypad.isColumnPressed(0))
{
if (digitalRead(lamp) == LOW)
{
digitalWrite(lamp, HIGH);
}
else
{
digitalWrite(lamp, LOW);
}
}

reading = analogRead(sensor);
if (reading >= 90) {
unsigned long currentMillis = millis();

if (currentMillis - previousMillis > 1500) {


previousMillis = currentMillis;

if (State == LOW)
{ State = HIGH;
Buzzer.buzzOn();
}

else
{ State = LOW;
Buzzer.buzzOff();
}

}
}
else
{
Buzzer.buzzOff();
}

pattern();

void pattern() {

if (Pattern.isNewPatternReceived())
{
PatternNode * patternEntered = Pattern.getLastPattern();

length = Pattern.getLastPatternLength();
if (length == 5)
{

for (int i = 0; i < length ; i++)


{

if (patternEntered[i].row == patternStored[i].row && patternEntered[i].col ==


patternStored[i].col)
{
counter++;
}
}

if (counter == 5)
{
digitalWrite(Lock, HIGH); // lock is high when opened
Email.send("[email protected]", "Your Home Security", "Your home was accessed
right now!");
taken =0;
}
else
{
digitalWrite(Lock, LOW);
if (taken ==0){
Camera.setFlash(ON);
Camera.rearCapture();
taken = 1;
}
Email.attachLastPicture ("[email protected]", "Your Home Security", "Someone tried
to access your home and we took a picture of him", 0);
counter = 0;
}
}
else
{

digitalWrite(Lock, LOW);
if (taken ==0){
Camera.setFlash(ON);
Camera.rearCapture();
taken = 1;
}
Email.attachLastPicture ("[email protected]", "Your Home Security", "Someone tried
to access your home and we took a picture of him", 0);

}
}
}
150) Garage Door Opener with Modem and Arduino Projet

COMPONENTS AND SUPPLIES


Siemens TC35i MC35i Terminal
Wireless WAN GPRS GSM
MODEM × 1

SparkFun Arduino Pro Mini 328 -


5V/16MHz
× 1

Male MAX3232 RS232 to TTL


Serial Port Converter Module DB9
Connector MAX232 × 1

MikroElektronika RELAY click

× 1

Wireless remote contoller for


garage door × 1

ABOUT THIS PROJECT


This is a GSM gateway (Siemen TC35i) that can be operated with a
garage door opening and closing device. The cause of the project is that
the Beninca remote control very expensive but quickly wears out
(breaks crack, etc.). I found out that I would use Arduino Mini Pro and
a GSM module. Because a mobile is almost handy and only one remote
control is in use. The remote control alignment does not want to
prevent switching, so only a simple relay operates a remote control.
The code is half simplicity, but it is not really elegant.There is no fault
tolerance if there is no modem or something is wrong, there is no
feedback. However, it only works with numbers that are included in the
database. Neither SMS or any other call responds. The call is rejected
at the same time (if there is a number in the database and if not if it is
not in the database).

SCHEMATICS
CODE
#include <SoftwareSerial.h> //Including Sotware
Serial lib for second serial port to connect Siemens TC35i

String tel_1 = "+11221234567"; //Telephone number 1


String tel_2 = "+11227654321"; //Telephone number 2

String temp; //Define temp


string

int rxpin = 9; //Define rx and tx


pin
int txpin = 8;

byte door = 10; //Relay output

SoftwareSerial serial2(rxpin,txpin); //RX,TX


void setup() {

pinMode(door, OUTPUT); //Set relay port to output


digitalWrite(door, HIGH); //Set relay port to high
(switch relay default state)

Serial.begin(115200); //Initialize HW serial port for debug


serial2.begin(57600); //Initialize SW serial port for
communicat with modem

Serial.println("Starting...."); //Program starting

delay(120000); //Waiting for modem


(120sec is enough)
serial2.println("at"); //Send AT Command
Serial.println("at");
temp = serial2.readString();
Serial.print(temp);
delay(1000);

Serial.println("at+clip=1"); //Send AT Command to receiving


caller ID
serial2.println("at+clip=1");
temp = serial2.readString();
Serial.println(temp);
delay(1000);

Serial.println("Enter to loop..."); //Loop is stating...

void loop() {

digitalWrite(door, HIGH); //Set relay outpout to high (relay normal


state)

if (serial2.available()) { //Wait for SW Serial communication is active


String str = serial2.readString(); //Read out full string from SW serial
temp = (str.substring(18,30)); //Parser out from only Caller ID
Serial.println(str.substring(18,30)); //Show Caller ID (only ID, without any text. Example:
RING ect..

if (temp == tel_1) //Find caller id in database


{
Serial.println("Telephone number 1"); //Print caller id in debug port
serial2.println("AT H"); //Hang up the call/ring
dooropen(); //Open the door
}

if (temp == tel_2) //Find caller id in database


{
Serial.println("Telephone number 2"); //Print caller id in debug port
serial2.println("AT H"); //Hang up the call/ring
dooropen(); //Open the door
}

else {
Serial.println("Unknow number door sill locked"); //Print to debug port
serial2.println("AT H"); //Hang up the call/ring
temp = serial2.readString(); //Eliminate "OK" feedback to AT H command

void dooropen()
{
Serial.println("Opening the door"); //Print to debug port
digitalWrite(door, LOW); //Set relay output LOW, activate the relay
delay(1000); //Wait 1 sec
digitalWrite(door, HIGH); //Set relay output HIGH, relay normal state
}
151) Arduino Copy Of Fidget Spinner RPM Counter Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO
× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1

Resistor 221 ohm

× 3

LED (generic)

× 3

hall effect sensor


× 2

Jumper wires (generic)

× 1

Single Turn Potentiometer- 10k


ohms
× 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Parts Required:
Fidget Spinner
neodyimium magnet(strong)
Arduino Uno
LED + resistor 220 Ohm
Hall-Effect Sensor - a3144
Single Turn Potentiometer
Jumper Wires
Breadboard
LCD 1602
2: Hall-Effect Sensor
Using Hall-Effect Sensor we can measure the speed of rotation. I used
Hall-Effect Sensor - a3144. I use two of it to make it easier to detect
RPM (Revolutions per minute) – the number of revolutions per minute.
Revolutions per minute – a unit of measurement of rotational speed: the
number of complete rotations made by the body (fidget spinner, wheel
etc.) around a fixed axis. Used to describe the speed of rotation of the
mechanical components in the mechanisms and machines.
3: How does it work?
To measure the speed of rotation on the Fidget Spinner must be mounted a
part of neodyimium magnet that affect the Hall sensor after each complete
turn of the Spinner.
4: Indication
The presence of a magnetic field is indicated on the LED. Left and Right
LED is keep shinning for some visual imporvement. LED in the middle
will only light up when magnet detected by hall-effect sensor.
LCD 1602 indicates current RPM, maximum RPM and tachometr bar
(from 0 up to 1260rpm). 1020 rpm is my personal record.
SCHEMATICS
CODE
#include <LiquidCrystal.h>
LiquidCrystal lcd(13,12,11,10,9,8);
const int hallSensorPin = 2; // connect the hall effect sensor on pin 2
const unsigned long sampleTime = 1000;
const int maxRPM = 1260; // maximum RPM for LCD Bar
int rpmMaximum = 0;

void setup()
{
pinMode(hallSensorPin,INPUT);
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("Initializing");
delay(1000);
lcd.clear();
lcd.print("Welcome to Fidget Spinner RPM Counter");
for (int positionCounter = 0; positionCounter < 21; positionCounter++) {
lcd.scrollDisplayLeft();
delay(350);
}
delay(1000);
lcd.clear();
}

void loop()
{
delay(100);
int rpm = getRPM();
if (rpm > rpmMaximum) rpmMaximum = rpm;
lcd.clear();
displayRPM(rpm);
displayBar(rpm);

int getRPM()
{
int count = 0;
boolean countFlag = LOW;
unsigned long currentTime = 0;
unsigned long startTime = millis();
while (currentTime <= sampleTime)
{
if (digitalRead(hallSensorPin) == HIGH)
{
countFlag = HIGH;
}
if (digitalRead(hallSensorPin) == LOW && countFlag == HIGH)
{
count++;
countFlag=LOW;
}
currentTime = millis() - startTime;
}
int countRpm = int(60000/float(sampleTime))*count;
return countRpm;
}

void displayRPM(int rpm)


{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(rpm,DEC);
lcd.setCursor(7,0);
lcd.print(rpmMaximum, DEC);
lcd.setCursor(13,0);
lcd.print("MAX");
Serial.print("RPM = ");
Serial.print(rpm);
Serial.print(" MAX RPM = ");
Serial.println(rpmMaximum);
}

void displayBar(int rpm)


{
int numOfBars=map(rpm,0,maxRPM,0,15);
lcd.setCursor(0,1);
if (rpm!=0)
{
for (int i=0; i<=numOfBars; i++)
{
lcd.setCursor(i,1);
lcd.write(1023);
}
}
}
152) Arduino Bluetooth Controlled Home Light Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

ControlEverything.com 4-
CHANNEL RELAY
CONTROLLER FOR I2C × 1
HC-05 Bluetooth Module

× 1

LED Light Bulb, Frosted GLS

× 1

Power Supply Accessory,


Interchangeable AC Input Plug
× 1

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Rocker Switch, Non Illuminated

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Objective
The objective of this project is to build up a system to operate an AC light
by using our Android phone.
Connections
A) Connections between Bluetooth Module and Arduino
+5V(Arduino) to +5V(Bluetooth)
GND(Arduino) to GND(Bluetooth)
RX(Arduino) to TX(Bluetooth)
TX(Arduino) to RX(Bluetooth)
B) Connections between Relay and Arduino
+5V(Arduino) to VCC(Relay)
GND(Arduino) to GND(Relay)
Digital Pin 8(Arduino) to IN1(Relay)
Digital Pin 9(Arduino) to IN2(Relay)
C) Connections between Relay, Switch board and Bulb
NO(Normally Open) pin(Relay) to Bulb-1
Common pin(Relay) to Switch Board(Switch-1)
NO(Normally Open) pin(Relay) to Bulb-2
Common pin(Relay) to Switch Board(Switch-2)
GND(Bulb-1) to GND(AC Supply - Negative Terminal)
GND(Bulb-2) to GND(AC Supply - Negative Terminal)
Switch Board(Switch-1) to AC Supply - Positive Terminal
Switch Board(Switch-2) to AC Supply - Positive Terminal
Bluetooth Application Setup
We have used an Android Application named "Bluetooth Electronics"
Google Play Store Link: https://play.google.com/store/apps/details?
id=com.keuwl.arduinobluetooth
First download and install the application from "Play Store"

Andoid Application
Edit a new panel
Add new panel
Add 2 switches and edit their Turn On Status according to the code

Add 2 switches
Now click on the "Connect" button and select "Bluetooth Classic" option
then click "Next" button
Connect with Bluetooth
After that pair with this application with "HC-05 Bluetooth Module" and
click "Done" button. Finally Click "Run" button to start working with this
app.

Pairing
Warning
Do not touch any wires while connecting the system with AC Supply
Do not disconnect any connections during powering up the system.
Complete all the connections properly.

SCHEMATICS
CODE
int input1=8;
int input2=9;
void setup() {
pinMode(input1, OUTPUT);
pinMode(input2,OUTPUT);
Serial.begin(9600);
}

void loop() {

if(Serial.available()>0)
{
char data= Serial.read();
switch(data)
{
case 'a': digitalWrite(input1, HIGH);
break;

case 'b': digitalWrite(input1, LOW);


break;

case 'c': digitalWrite(input2, HIGH);


break;

case 'd': digitalWrite(input2, LOW);


break;

default : break;
}
Serial.println(data);
}
delay(50);
}
153) Arduino Working with Shift Register Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO
× 1

Breadboard (generic)

× 1

8 bit Shift Register (74HC595)


× 1

LED (generic)

× 8

Resistor 1k ohm

× 8

Jumper wires (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


This project demonstartes the working with Shift Register.
Objective:
Blink all the LEDs together.
Switching ON one by one and then switching OFF one by one.

SCHEMATICS
CODE

Code to make all LEDs blink together .

const int DataPin = 2;


const int ClockPin = 3;
const int LatchPin = 4;
void setup()
{
pinMode (DataPin, OUTPUT);
pinMode (ClockPin, OUTPUT);
pinMode (LatchPin, OUTPUT);
}

void loop()
{
digitalWrite (LatchPin, LOW);
shiftOut (DataPin, ClockPin, LSBFIRST, 255);
digitalWrite (LatchPin, HIGH);
delay (1000);
digitalWrite (LatchPin, LOW);
shiftOut (DataPin, ClockPin, LSBFIRST, 0);
digitalWrite (LatchPin, HIGH);
delay (1000);
}

LEDs will be ON one by one and will be OFF one by one

const int DataPin = 2;


const int ClockPin = 3;
const int LatchPin = 4;

byte Data = 0;
void setup()
{
pinMode (DataPin, OUTPUT);
pinMode (ClockPin, OUTPUT);
pinMode (LatchPin, OUTPUT);
}

void loop()
{
shiftWrite (0,1);
delay(1000);
shiftWrite (1,1);
delay(1000);
shiftWrite (2,1);
delay(1000);
shiftWrite (3,1);
delay(1000);
shiftWrite (4,1);
delay(1000);
shiftWrite (5,1);
delay(1000);
shiftWrite (6,1);
delay(1000);
shiftWrite (7,1);
delay(1000);
shiftWrite (0,0);
delay(1000);
shiftWrite (1,0);
delay(1000);
shiftWrite (2,0);
delay(1000);
shiftWrite (3,0);
delay(1000);
shiftWrite (4,0);
delay(1000);
shiftWrite (5,0);
delay(1000);
shiftWrite (6,0);
delay(1000);
shiftWrite (7,0);
delay(1000);
}

void shiftWrite(int Pin, boolean State)


{
bitWrite (Data, Pin, State);
digitalWrite (LatchPin, LOW);
shiftOut (DataPin, ClockPin, MSBFIRST, Data);
digitalWrite (LatchPin, HIGH);
}
154) LED Matrix Arduino Flip Clock Projet

COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

Maxim Integrated DS3231M -


±5ppm, I2C Real-Time Clock
× 1
8x8 Led matrix with MAX7219
driver × 1

RGB Diffused Common Cathode

× 1

Resistor 220 ohm

× 2

Rotary Encoder with Push-Button

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


I build this 8x8 LED Matrix Module CLOCK developed by Adrian
Jones.Time is displayed by scrolling from left to right, or, under software
control, from top to bottom. Each digit of the time successively slides in
from the right side and when centered, stops momentarily and brightens
slightly. It then scrolls to the left while the next digit in the display scrolls
into view. The cycle repeats with a short delay between successive
displays.For "from top to bottom" vertical flipping you should change :
static boolean top2bottom = false;
to:
static boolean top2bottom = true;
As you can see in the comments of the code, many parameters can be
changed, for example scroll spreed, number of blank lines between
characters, 12/24 hour display, ms between characters, brightness etc..
Time can be easily set using a rotary encoder.A two-color diode displays
the setting mode (minutes, hours or normal).I put the clock in a box made
up of two basic pieces so the access to the inside of the box is very
convenient and practical.
SCHEMATICS
CODE
#include <Wire.h> // I2C-WIRE library
#include <RTClib.h> // RTC-Library

// define max7219 registers and control pins


#define max7219_reg_noop 0x00
#define max7219_reg_digit0 0x01
#define max7219_reg_digit1 0x02
#define max7219_reg_digit2 0x03
#define max7219_reg_digit3 0x04
#define max7219_reg_digit4 0x05
#define max7219_reg_digit5 0x06
#define max7219_reg_digit6 0x07
#define max7219_reg_digit7 0x08
#define max7219_reg_decodeMode 0x09
#define max7219_reg_intensity 0x0a
#define max7219_reg_scanLimit 0x0b
#define max7219_reg_shutdown 0x0c
#define max7219_reg_displayTest 0x0f
#define dataIn 12 // DIN
#define load 10 // CS
#define clock 11 // CLK

char alphanum[][8] ={{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // blank Hex 20


Dec 32
{0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10}, // ! 33
{0x00,0x28,0x28,0x28,0x00,0x00,0x00,0x00}, // " 34
{0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00}, // # 35
{0x10,0x38,0x50,0x38,0x14,0x54,0x38,0x10}, // $
{0x41,0xA2,0x44,0x08,0x10,0x22,0x45,0x82}, // %
{0x38,0x44,0x44,0x38,0x50,0x4A,0x44,0x3A}, // &
{0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00}, // '
{0x30,0x40,0x80,0x80,0x80,0x80,0x40,0x30}, // ( 40
{0xC0,0x20,0x10,0x10,0x10,0x10,0x20,0xC0}, // )
{0x28,0x10,0xAA,0x54,0xAA,0x10,0x28,0x00}, // *
{0x00,0x10,0x10,0x10,0xFE,0x10,0x10,0x10}, // +
{0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10}, // ,
{0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18}, // .
{0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}, // /
{0x7E,0xC1,0xA1,0x91,0x89,0x85,0x83,0x7E}, // 0
{0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x7C}, // 1
{0x38,0x44,0x82,0x04,0x18,0x20,0x40,0xFE}, // 2 50
{0x7C,0x82,0x02,0x3C,0x02,0x02,0x82,0x7C}, // 3
{0x08,0x18,0x28,0x48,0xFE,0x08,0x08,0x08}, // 4
{0xFE,0x80,0xF8,0x04,0x02,0x82,0x44,0x38}, // 5
{0x38,0x44,0x80,0xB8,0xC4,0x82,0x44,0x38}, // 6
{0xFE,0x02,0x04,0x08,0x10,0x20,0x20,0x20}, // 7
{0x7C,0x82,0x82,0x7C,0x82,0x82,0x82,0x7C}, // 8
{0x7C,0x82,0x82,0x7E,0x02,0x82,0x44,0x38}, // 9
{0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x00}, // :
{0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x30}, // ;
{0x00,0x10,0x20,0x40,0x80,0x40,0x20,0x10}, // < 60
{0x00,0x00,0x00,0x7E,0x00,0x7E,0x00,0x00}, // =
{0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80}, // >
{0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20}, // ?
{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}, // n 110
{0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38}, // o
{0x00,0x00,0x70,0x48,0x48,0x70,0x40,0x40}, // p
{0x00,0x00,0x30,0x48,0x48,0x38,0x08,0x08}, // q
{0x00,0x00,0x00,0x30,0x48,0x40,0x40,0x40}, // r
{0x00,0x30,0x48,0x40,0x30,0x08,0x48,0x30}, // s
{0x00,0x20,0x70,0x20,0x20,0x20,0x28,0x10}, // t
{0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x38}, // u
{0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10}, // v
{0x00,0x00,0x82,0x82,0x82,0x92,0x54,0x28}, // w
{0x00,0x00,0x84,0x48,0x30,0x30,0x48,0x84}, // x 120
{0x00,0x48,0x48,0x48,0x38,0x08,0x48,0x30}, // y
{0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x7C}, // z
{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} // pm codes as '~' Hex 7E, Dec 126
};

// define RTC operation


RTC_DS1307 RTC; // 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); // mode pin
digitalWrite(mode_Pin, 1);
pinMode(min_Pin, OUTPUT); // minute pin
digitalWrite(min_Pin, 1);

// encoder control
pinMode(enc_PinA, INPUT_PULLUP); digitalWrite(enc_PinA, HIGH); // rotary
encoder pin A
pinMode(enc_PinB, INPUT_PULLUP); digitalWrite(enc_PinB, HIGH); // rotary
encoder pin B
pinMode(enc_Switch, INPUT_PULLUP);digitalWrite(enc_Switch, HIGH); // encoder
switch
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<=8; e++) {maxSingle(e,0); } // clear LED registers (turn all LEDs off)
maxSingle(max7219_reg_intensity, 0x00); // set intensity. Range: 0x00 to 0x0f
}

// function adjTime(): increments/decrements (based encoder direction) hours/mins


(depending on mode)
void adjTime(DateTime now, boolean dir) {
if(mode == 1) { // adjust hours
int adj_hrs = now.hour();
if(dir) { // increment
if(++adj_hrs >= 25) adj_hrs = 1;
} else { // decrement
if(adj_hrs == 0) adj_hrs = 24;
if(--adj_hrs <= 0) adj_hrs = 24;
}
RTC.adjust(DateTime(now.year(), now.month(), now.day(), adj_hrs, now.minute(),
now.second() ));
}

if(mode == 2) { // adjust minutes


int adj_mins = now.minute();
if(dir) {
if(++adj_mins >= 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 << (7-col);
for (int row = 0; row < 8 ; row++) { bitWrite(rc[col], 7-row,(alphanum[ind][row] & mask));
}
}
}

// function show_time_and_date: print out time string & bytes


void show_time_and_date(DateTime datetime){
if(doSerial) {
int minutes = datetime.minute();
int hours = datetime.hour(); if(hours==0) hours=24;
int seconds = datetime.second();
char delim = '/'; char dend = ' ';
String te = "Current date/time: ";
te = te + datetime.year() + delim + datetime.month() + delim + datetime.day() + dend;

Serial.print(te);
if(hours<10) Serial.print(0); Serial.print(hours,DEC);
Serial.print(":");
if(minutes<10) Serial.print(0); Serial.print(minutes,DEC);
Serial.print(":");
if(seconds < 10) Serial.print(0); Serial.print(seconds,DEC);
Serial.println("");
}
}

String createMessage(DateTime datetime) {


String new_mess = " ";
int hr = datetime.hour()%24; if(hr == 0) hr = 24;
int mn = datetime.minute();
if(mode == 0) { // Normal mode
if(hour24) {
new_mess += hr;
} else {
new_mess += (hr > 12)? hr - 12 : hr;
}
new_mess += ':';
if(mn < 10) new_mess += '0'; new_mess += mn;
if(!hour24) new_mess += (hr > 12)? "~" : "^";
}

if(mode == 1) { // Adjusting hours


new_mess += hr;
}

if(mode == 2) { // Adjusting minutes


if(mn < 10) new_mess += '0'; new_mess += mn;
}
return new_mess;
}

// function initDisplayString() : creates array of message string with blanks between


characters and at end
int initDisplayString(String message) {
int x = 0;
for (int y = 0; y < message.length(); y++ ){
char thisCh = message.charAt(y);
int ind = int(thisCh) - 0x20;
if(!top2bottom) rotChar(thisCh);
for (int row = 0; row < 8 + cblanks; row++) {
if (row <= 7) {
ac[x] = (top2bottom)? alphanum[ind][7-row] : rc[row];
} else {
ac[x] = 0;
}
x++;
}
}

for(int y = 0; y < 7+eblanks; y++) {ac[x] = 0; x++; } // end blanks


return x;
}
// function maxSingle() : loads data into register
void maxSingle(byte reg, byte col) {
digitalWrite(load, LOW); // begin
putByte(reg); // specify register
putByte(col); // ((data & 0x01) * 256) + data >> 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 << (i - 1); // create bitmask
digitalWrite(clock, LOW); // tick
if (data & mask){ // choose bit
digitalWrite(dataIn, HIGH);// send 1
} else {
digitalWrite(dataIn, LOW); // send 0
}
digitalWrite(clock, HIGH); // tock
--i; // move to lesser bit
}
}
155) Arduino Hazardaus Gas Detector with LED Indication Projet
COMPONENTS AND SUPPLIES

Arduino Gemma

× 1

SparkFun Step-Up Voltage


Regulator - 5V
× 1

RFduino Battery Shield


× 1

SparkFun LED
× 1

Breadboard (generic)

× 1

MQ 9 Hazardous Gas Sensor


× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
Arduino IDE

circuito.io

ABOUT THIS PROJECT

It is important to know whether the gas coming out is hazardous or not.


So I built this small handy or wearable sensor to know about hazardous
gases. It gives LED indication on detection of hazardous gas coming.
Powering Gemma
Connect battery positive and negative terminal to Gemma BAT+ and
BAT- respectively.
Connecting MQ9 Sensor
Connect MQ9 GND to GND
Connect MQ9 5V to %v step up converter.
Connect MQ9 Ground to Gemma D2 Via 100 ohm resistor.
Connect MQ9 GND to MQ9 D0 via 100 ohm resistor.
Connecting LED
Connect LED GND to GND via 100 ohm resistor.
Connect LED Vin to Gemma D0.

SCHEMATICS
CODE
// Include Libraries
#include "Arduino.h"
// Pin Definitions
#define LEDRed_PIN_VIN 0
#define MQ9_PIN_AOUT 2

// Setup the essentials for your circuit to work. It runs first every time your
circuit is powered with electricity.
void setup()
{
// Setup Serial which is useful for debugging
// Use the Serial Monitor to view printed messages
Serial.begin(9600);
while (!Serial) ; // wait for serial port to connect. Needed for native USB
Serial.println("start");

// Main logic of your circuit. It defines the interaction between the


components you selected. After setup, it runs over and over again, in an
eternal loop.
void loop()
{
}

156) Arduino Etch A Sketch Joystick Projet

COMPONENTS AND SUPPLIES


DC motor (generic)
× 1

Analog joystick (Generic)


× 1

Arduino Nano R3

× 1
NECESSARY TOOLS AND MACHINES
3D Printer (generic)

Hot glue gun (generic)

ABOUT THIS PROJECT

Step 1: Physical Build


I made a simple frame out of cardboard and hot glue, but I ended up 3D-
printing an adapter piece for the motor. Here's how to build it:
Print two adapter pieces (file is below)
Fit the motors in place - you may need to use a heat gun or blow drier to
help it fit
Cut and glue pieces of cardboard around the motors to hold them at a 90°
angle, make sure they can't move around
Attach a breadboard, battery holder, and a place for the Wii remote to rest
Step 2: Circuit
Make the circuit as shown above:
You may want to use a higher voltage battery than shown
More information about using a Wii remote with Arduino
Step 3: Code
Upload this code in the Arduino IDE (Wii remote functions from Tod
Kurt's library):
#include <Wire.h>
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
//#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);
}
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 <Wire.h>
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
//#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

SparkFun Flex Sensor


× 2

Buzzer

× 1

Resistor 10k ohm

× 2
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, Multi-
platform 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 <EEPROM.h>
#include <SPI.h>
char auth[] = "**************"; //Blynk Authorization Code
WidgetTerminal terminal(V2);
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 <Wire.h>
/*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 <BlynkSimpleCurieBLE.h>
#include <CurieBLE.h>
#include <Wire.h>
#include <EEPROM.h>
#include <SPI.h>

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;i<100;i++){
flx1 = analogRead(flex1); //Get raw readings from sensors
flx2 = analogRead(flex2);
x = CurieIMU.readAccelerometer(X_AXIS)/100;
y = CurieIMU.readAccelerometer(Y_AXIS)/100;
z = CurieIMU.readAccelerometer(Z_AXIS)/100;
delay(2);
}
flx1=flx1/100;
flx2=flx2/100;
x = x/100; //Get the average values of the readings
y = y/100;
z = z/100;
}

void setup(){
//pinMode(3,OUTPUT);
pinMode(flex1,INPUT);
pinMode(flex2,INPUT); //Setting the sensor pin modes
Serial.begin(9600);

blePeripheral.setLocalName("Arduino101Blynk");
blePeripheral.setDeviceName("Arduino101Blynk");
blePeripheral.setAppearance(384);
Blynk.begin(auth, blePeripheral);
blePeripheral.begin();

m_flx1 = EEPROM.read(0);
m_flx2 = EEPROM.read(1);
m_x = EEPROM.read(2); //Read pre saved sensor values from EEPROM
m_y = EEPROM.read(3);
m_z = EEPROM.read(4);

void loop(){
Blynk.run();
blePeripheral.poll();

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);
}

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

Resistor 100k ohm

× 4

Through Hole Resistor, 22 kohm


× 1

Capacitor 100 nF

× 2

Alphanumeric LCD, 16 x 2

× 1
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 <LiquidCrystal.h>

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 <= 16; i++)


{
lcd.setCursor(0, 0);
lcd.print(KTAudio.substring(0, i));
delay(50);
}

KTAudio = "VU meter " + main_version;

for (int i = 0; i <= KTAudio.length(); i++)


{
lcd.setCursor(0, 1);
lcd.print(KTAudio.substring(0, i));
delay(50);
}

delay(500);

lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Loading...");

for (int i = 0; i < 16; i++)


{
lcd.setCursor(i, 1);
lcd.write(4);
}

for (int i = 0; i < 16; i++)


{
lcd.setCursor(i, 1);
lcd.write(1);

delay(50);
}

delay(500);
lcd.clear();

decayTime = millis();
}

void loop()
{
actualMillis = millis();

lcd.setCursor(0, 0); //L channel index


lcd.write(2); //L symbol
lcd.setCursor(0, 1); //R channel index
lcd.write(3); //R symbol
lcd.setCursor(15, 0); //closing tag / end mark index 1
lcd.write(5); //closing tag / end mark
lcd.setCursor(15, 1); //closing tag / end mark index 2
lcd.write(5); //closing tag / end mark

totalL = analogRead(inputPinL) / 4 - 128; //reducing the detected hum and noise

if(totalL > maxL)


{
maxL = totalL;
}

indexL++;

if (indexL >= 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

Photo resistor

× 3
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

Jumper wires (generic)

× 1

Breadboard (generic)

× 1

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 <= 0:
ball_x = 0
game_lost = True
loss_message = "Player 2 won! Player 1 is pretty sucky though..."
# Check if the ball has bounced off the left paddle
if ((ball_x <= left_paddle_x) and (ball_y >= left_paddle_y) and (ball_y <=
(left_paddle_y + PADDLE_HEIGHT))):
dx = -dx
ball_x = left_paddle_x + 1
# Check to see if the ball has bounced off the right paddle
if ((ball_x >= right_paddle_x) and (ball_y >= right_paddle_y) and (ball_y
<= (right_paddle_y + PADDLE_HEIGHT))):
dx = -dx
ball_x = right_paddle_x - 1
# Check to see if the ball hit the bottom wall
if ball_y >= (HEIGHT - 1):
ball_y = HEIGHT -1
dy = -dy
# Check to see if the ball hit the top wall
if ball_y <= 0:
ball_y = 0
dy = -dy

# Check to see if the paddle does not pass through the top
if left_paddle_y <= 0:
left_paddle_y = 0
# Check to see if the paddles do not pass through the bottom
if left_paddle_y >= (HEIGHT - PADDLE_HEIGHT):
left_paddle_y = (HEIGHT - PADDLE_HEIGHT)
if right_paddle_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

SG90 Micro-servo motor

× 4

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.h> //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<array_index; Play_action++) //Navigate through every
saved element in the array
{
action_servo = saved_data[Play_action] / 1000; //The fist character of the array element is
split for knowing the servo number
action_pos = saved_data[Play_action] % 1000; //The last three characters of the array
element is split to know the servo postion

switch(action_servo){ //Check which servo motor should be controlled


case 0: //If zeroth motor
Servo_0.write(action_pos);
break;

case 1://If 1st motor


Servo_1.write(action_pos);
break;

case 3://If 3rd motor


Servo_3.write(action_pos);
break;

case 4://If 4th motor


Gripper.write(action_pos);
break;
}

delay(50);

}
}

void loop() {

if (Serial.available() > 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

× 1

Adafruit MLX90614
× 1

Microchip AVR for Arduino


× 1
328P/168P/8A
SparkFun 7-Segment Serial Display
- Red × 1
3 digit display used

Breadboard (generic)
8x2 cm
× 2

16 MHz Crystal

× 1

Slide Switch

× 1

30 mm Red Push Switch


× 1
any big red push switch
22 mm White Push Switch
× 1

Buzzer

× 1

Colored pin header (generic)


× 1

MLX90614 IR Temperature Sensor


× 1

LED Dot Laser (generic)


× 1

USB A Connector
× 1

AMS1117 3.3V Voltage Regulator


× 1

150 mAH 3.7V LiPo battery


× 1
cylindrical
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 <Wire.h>
#include <Adafruit_MLX90614.h>

#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

× 1

Single Turn Potentiometer- 10k


ohms
× 1
Resistor 10k ohm

× 1

Resistor 4.75k ohm

× 1

Diode 1N4148
× 1

Capacitor 10 µF

× 1

Ferrite Core Round Cable

× 2

Connector 3.5 mm (1/8)


× 1

Connector Icom tuner (computer


supply) × 1
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 <SoftwareSerial.h> // 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 S-


meter value on the S-meter output pin.
delay(20);
}
}
}
}
164) Arduino Electric Bike Projet

COMPONENTS AND SUPPLIES

Arduino Micro & Genuino Micro

× 1

Motor Heat Sink w/Fan Red


Aluminum (27mm) × 1

Female XT60 Connectors


× 5

Male XT60 Connectors


× 5

24AWG Silicone Wire


× 1

6mm Wire Mesh Guard


× 1

3 Function Switch w/UBEC,


Voltage Display × 1

Female JST Battery Pigtail


× 5

Male JST Battery Pigtail


× 5

LED Strip with JST Female


Connector 200mm (Red) × 1

Round 2-Way Switch (Short)


× 1

Police Car LED Lighting System


× 1

JST-SH Servo Plug Set


× 1
Ultrasonic Sensor - HC-SR04
(Generic) × 1

LM386 Audio Amplifier Module


with 10K Resistance × 1

MicroSD Module
× 1

12mm Push Button Switch


× 1

DPDT 6 Terminal 2 Position


Rocker Switch × 1

20 Wire Rainbow Color Flat


Ribbon Cable × 1

Micro-USB to USB Cable


(Generic)
× 1

USB Female Socket Connector with


Plastic Cover × 1

Female Header 8 Position 1 Row


(0.1")
× 3
Need pieces of 20 positions

Right Angle Single Row Female


Header × 1

Male Header 40 Position 1 Row


(0.1")
× 1

Dupont Connector Kit


× 1

10x5cm Prototype Board


× 1

2S LiFe Battery
× 1

2S LiPo Battery
× 1

Spade Wire Connector


× 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 pre-
recorded 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 <SD.h>
#include <TMRpcm.h>
#include <SPI.h>

#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) << 3;
state += debounce(PIN_SW_REVERSE) << 2;
state += debounce(PIN_SW_SIREN) << 1;
state += debounce(PIN_SW_HONK);

if (last_state != state) {
DPRINT("state: ");
DPRINTLN(state);
}
last_state = state;

switch (state) {
case B0000:
giroflex(0);
reset_siren();
audio.disable();
noTone(PIN_SPEAKER);
break;
case B0011:
case B0010:
case B1010:
if (count_siren < 10) {
count_siren++;
DPRINT("siren button hold :");
DPRINTLN(count_siren);
} else {
giroflex(2);
if (!audio.isPlaying())
audio.play("s2.wav");
}
break;
case B0101:
case B0100:
case B0110:
case B0111:
giroflex(0);
case B1100:
case B1101:
case B1110:
case B1111:
count_siren = 0;
audio.disable();
parking();
break;
case B1000:
reset_siren();
audio.disable();
noTone(PIN_SPEAKER);
giroflex(5);
break;
case B0001:
giroflex(0);
reset_siren();
if (!audio.isPlaying()) {
audio.play("honk.wav");
while (audio.isPlaying());
}
break;
case B1001:
reset_siren();
case B1011:
giroflex(5);
if (!audio.isPlaying()) {
audio.play("honk.wav");
while (audio.isPlaying());
}
break;
}
}

void reset_siren() {
if (count_siren > 0 and count_siren < 10) {
giroflex(3);
audio.disable();
audio.play("s1.wav");
while (audio.isPlaying());
giroflex(0);
}
count_siren = 0;
}

void parking() {
DPRINTLN("parking");
pinMode(PIN_SPEAKER, OUTPUT);
noTone(PIN_SPEAKER);
tone(PIN_SPEAKER, 440, 100);
delay(500);

while (digitalRead(PIN_SW_REVERSE) == LOW) {


digitalWrite(PIN_SENSOR_TRIGGER, HIGH);
delayMicroseconds(5);
digitalWrite(PIN_SENSOR_TRIGGER, LOW);
unsigned long int tt = pulseIn(PIN_SENSOR_ECHO, HIGH);
if (tt > 2000) {
noTone(PIN_SPEAKER);
continue;
}
tt = (tt < 500) ? 500 : tt;
int d = map(tt, 2000, 500, 500, 0);
tone(PIN_SPEAKER, 440, 100);
delay(d);
}

noTone(PIN_SPEAKER);
DPRINTLN("no parking");
}

int debounce(int but) {


int count = 0;
do {
delay(1);
count++;
if (count >= 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

× 1

DFRobot 6 DOF Sensor -


MPU6050
× 1

DC Motor, 12 V
× 2

L298N Driver Motor


× 1

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Male/Female Jumper Wires

× 1

SG90 Micro-servo motor

× 2

9V battery (generic)
to power the Arduino board
× 1

AA Batteries
To power the DC motor
× 8
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 <Wire.h> //include the required libraries
#include <MPU6050.h> //include MPU6050 libraries
#include <Servo.h>
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 ; //declare 6 16 bit integer variables


int16_t gx, gy, gz ; //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); //Read the incoming data and store it into variable 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();
}
}
}
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 left-
right 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 3-
wire 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 <Servo.h>
//Initialize variables
int mode = 0;
int axe = 0;
int buttonState1 = 0;
int buttonState2 = 0;
int prevButtonState1 = 0;
int prevButtonState2 = 0;

int ldrtopr= 0; // top-right LDR


int ldrtopl = 1; // top-left LDR
int ldrbotr = 2; // bottom-right LDR
int ldrbotl = 3; // bottom-left LDR
int topl = 0;
int topr = 0;
int botl = 0;
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); //Mode switch Button


pinMode(11, INPUT); //Axis switch
pinMode(A4, INPUT); //Potentiometer for right-left movement and for up-down
movement

servo_updown.attach(5); //Servo motor up-down movement


servo_rightleft.attach(6); //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; //average of top LDRs
int avgbot = (botr + botl) / 2; //average of bottom LDRs
int avgleft = (topl + botl) / 2; //average of left LDRs
int avgright = (topr + botr) / 2; //average of right LDRs

//Get the different


int diffelev = avgtop - avgbot; //Get the different average betwen LDRs top and LDRs
bot
int diffazi = avgright - avgleft; //Get the different average betwen LDRs right and LDRs
left

//left-right movement of solar tracker

if (abs(diffazi) >= threshold_value){ //Change position only if light difference is bigger


then the threshold_value
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

Real Time Clock (RTC)

× 1

Jumper wires (generic)


× 1

0.91 Inch 128x32 IIC I2C Blue


OLED LCD Display DIY Oled
Module SSD1306 Driver IC DC × 1
3.3V 5V For Arduino PIC

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 <Wire.h>
#include "RTClib.h"
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#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)&&(mo<2)){
display.print("January ");
}
if ((mo>1)&&(mo<3)){
display.print("February ");
}
if ((mo>2)&&(mo<4)){
display.print("March ");
}
if ((mo>3)&&(mo<5)){
display.print("April ");
}
if ((mo>4)&&(mo<6)){
display.print("May ");
}
if ((mo>5)&&(mo<7)){
display.print("June ");
}
if ((mo>6)&&(mo<8)){
display.print("July ");
}
if ((mo>7)&&(mo<9)){
display.print("August ");
}
if ((mo>8)&&(mo<10)){
display.print("September ");
}
if ((mo>9)&&(mo<11)){
display.print("October ");
}
if ((mo>10)&&(mo<12)){
display.print("November ");
}
if ((mo>11)&&(mo<13)){
display.print("December ");
}

display.print (now.day(), DEC);

display.print(", ");

display.print (now.year(), DEC);


//set hour
display.setCursor(0,24);
int hr=now.hour();
if (hr>12){
hr=hr-12;
}
if ((hr>0)&&(hr<2)){
display.print("One ");
}
if ((hr>1)&&(hr<3)){
display.print("Two ");
}
if ((hr>2)&&(hr<4)){
display.print("Three ");
}
if ((hr>3)&&(hr<5)){
display.print("Four ");
}
if ((hr>4)&&(hr<6)){
display.print("Five ");
}
if ((hr>5)&&(hr<7)){
display.print("Six ");
}
if ((hr>6)&&(hr<8)){
display.print("Seven ");
}
if ((hr>7)&&(hr<9)){
display.print("Eight ");
}
if ((hr>8)&&(hr<10)){
display.print("Nine ");
}
if ((hr>9)&&(hr<11)){
display.print("Ten ");
}
if ((hr>10)&&(hr<12)){
display.print("Eleven ");

}
if ((hr>11)&&(hr<13)){
display.print("Twelve ");
}
// set minute

int m=now.minute();

if ((m>0)&&(m<2)){
display.print("O-One");
}
if ((m>1)&&(m<3)){
display.print("O-Two");
}

if ((m>2)&&(m<4)){
display.print("O-Three");
}
if ((m>3)&&(m<5)){
display.print("O-Four");
}
if ((m>4)&&(m<6)){
display.print("O-Five");
}

if ((m>5)&&(m<7)){
display.print("O-Six");
}

if ((m>6)&&(m<8)){
display.print("O-Seven");
}
if ((m>7)&&(m<9)){
display.print("O-Eight");
}

if ((m>8)&&(m<10)){
display.print("O-Nine");
}

//teens
if ((m>9)&&(m<11)){
display.print("Ten");
}
if ((m>10)&&(m<12)){
display.print("Eleven");
}

if ((m>11)&&(m<13)){
display.print("Twelve");
}

if ((m>12)&&(m<14)){
display.print("Thirteen");
}
if ((m>13)&&(m<15)){
display.print("Fourteen");
}

if ((m>14)&&(m<16)){
Serial.print("Fifteen");
}
if ((m>15)&&(m<17)){
display.print("Sixteen");
}
if ((m>16)&&(m<18)){
display.print("Seventeen");
}

if ((m>17)&&(m<19)){
display.print("Eighteen");
}

if ((m>18)&&(m<20)){
display.print("Ninteen");
}

//twenty
if ((m>19)&&(m<21)){
display.print("Twenty");
}

if ((m>20)&&(m<22)){
Serial.print("Twenty-One");
}
if ((m>21)&&(m<23)){
display.print("Twenty-Two");
}
if ((m>22)&&(m<24)){
display.print("Twenty-Three");
}

if ((m>23)&&(m<25)){
Serial.print("Twenty-Four");
}
if ((m>24)&&(m<26)){
display.print("Twenty-Five");
}
if ((m>25)&&(m<27)){
display.print("Twenty-Six");
}
if ((m>26)&&(m<28)){
display.print("Twenty-Seven");
}

if ((m>27)&&(m<29)){
Serial.print("Twenty-Eight");
}

if ((m>28)&&(m<30)){
display.print("Twenty-Nine");
}

// thirty
if ((m>29)&&(m<31)){
display.print("Thirty");
}

if ((m>30)&&(m<32)){
display.print("Thirty-One");
}
if ((m>31)&&(m<33)){
display.print("Thirty-Two");
}
if ((m>32)&&(m<34)){
display.print("Thirty-Three");

if ((m>33)&&(m<35)){
display.print("Thirty-Four");

if ((m>34)&&(m<36)){
display.print("Thirty-Five");

}
if ((m>35)&&(m<37)){
display.print("Thirty-Six");
}
if ((m>36)&&(m<38)){
display.print("Thirty-Seven");

if ((m>37)&&(m<39)){
display.print("Thirty-Eight");
}

if ((m>38)&&(m<40)){
display.print("Thirty-Nine");
}

//forty
if ((m>39)&&(m<41)){
display.print("Forty");
}

if ((m>40)&&(m<42)){
display.print("Forty-One");
}
if ((m>41)&&(m<43)){
display.print("Forty-Two");
}
if ((m>42)&&(m<44)){
display.print("Forty-Three");
}

if ((m>43)&&(m<45)){
display.print("Forty-Four");
}

if ((m>44)&&(m<46)){
display.print("Forty-Five");
}
if ((m>45)&&(m<47)){
display.print("Forty-Six");
}
if ((m>46)&&(m<48)){
display.print("Forty-Seven");
}

if ((m>47)&&(m<49)){
display.print("Forty-Eight");
}

if ((m>48)&&(m<50)){
display.print("Forty-Nine");
}

//fifty
if ((m>49)&&(m<51)){
display.print("Fifty");
}

if ((m>50)&&(m<52)){
display.print("Fifty-One");
}
if ((m>51)&&(m<53)){
display.print("Fifty-Two");
}
if ((m>52)&&(m<54)){
display.print("Fifty-Three");
}

if ((m>53)&&(m<55)){
display.print("Fifty-Four");
}

if ((m>54)&&(m<56)){
Serial.print("Fifty-Five");
}
if ((m>55)&&(m<57)){
display.print("Fifty-Six");
}
if ((m>56)&&(m<58)){
display.print("Fifty-Seven");
}

if ((m>57)&&(m<59)){
display.print("Fifty-Eight");
}

if ((m>58)){
display.print("Fifty-Nine");
}

if (m<1){
display.print("O'Clock");
}
display.print(" ");

int tm=now.hour();
if (tm<13){
display.print("AM");
}

if (tm>12){
display.print("PM");
}

display.display();
}
void loop()

{
Display();
delay(0);
}

168) Arduino Memory Gam Projet


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

IR NPN Phototransistor 3mm


× 4

Resistor 221k ohm

× 4
LED (generic)

× 4

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Resistor 1k ohm

× 4

Coin Cell Battery CR2032

ABOUT THIS PROJECT


Do you like playing games? This is the most simple implementation of
the Memory game. All you need is to use your memory to hack the
predefined sequence.

It was first and the pretty simple breadboard prototype. Scheme:


Initial breadboarding
But we wanted more. And we've decided to make it better.
First, we've changed the main board to Arduino Mega (due to the
number of ports).
Second, we've added the indication (16 LEDs)
Then we've added the sound (Just a piezoelectric speaker :))
We've designed the body for arduino and we've got the input device
(a toy gun) :)
And after a day of soldering, printing and coding, we've got the real
Memory game:
The second prototype with updated laser gun:)
So now, you just need to make shots and your aim is to fill the
progressbar.

After few days of debugging we've decided:


To mount it to the wall for our "children"
To add the programming mode, to be able to change the difficulty
(4..16)
To add the hidden button to enter/exit/reset the programming mode
To add the WOW effect:) to open the common drawer in the desk by
solving this puzzle
The final version of the game

SCHEMATICS
CODE

#define NOTE_G3 196


#define NOTE_B3 247
#define NOTE_C4 262

#include <EEPROM.h>

const byte MIN_SENSOR_VALUE = 45;


const byte MIN_TASK_DIFFICULTY = 4;
const byte MAX_TASK_DIFFICULTY = 16;

byte TASK_DIFFICULTY = MIN_TASK_DIFFICULTY;

byte programmingPort = 49; // Digital port


byte relayPort = 31; // Digital port
byte tonePort = 3; // PWM port
byte sensors[4]={1,0,2,3}; // Analog ports
byte sensorLEDs[4]={7,5,6,4}; // PWM output (invert to +5V, HIGH=LOW and
LOW=HIGH)
byte progressLEDs[MAX_TASK_DIFFICULTY]={26,28,30,32, 34,36,38,40, 42,44,46,48,
50,52,53,51}; // Digital ports
byte task[MAX_TASK_DIFFICULTY]={3,1,3,2, 3,1,4,1, 2,1,4,3, 2,1,4,1};

int melody1[] = {NOTE_B3, NOTE_G3, NOTE_C4}; //correct melody


int noteDurations1[] = {16,32,32};
int melody2[] = {NOTE_C4, NOTE_G3, NOTE_B3}; //wrong melody
int noteDurations2[] = {8,16,8};

int progress = 0; //current task/level


byte currentCode = 0;

boolean IsProgrammingMode = false;


boolean isTheEnd = false;

void Init()
{
IsProgrammingMode = false;
isTheEnd = false;
progress = 0;
currentCode = 0;

// getting settings from eeprom


TASK_DIFFICULTY = EEPROM.read(1);
if(TASK_DIFFICULTY <= MIN_TASK_DIFFICULTY)
{
TASK_DIFFICULTY = MIN_TASK_DIFFICULTY;
}

for(byte i=0; i<MAX_TASK_DIFFICULTY; i++)


{
pinMode(progressLEDs[i], OUTPUT);
}
for(int i=0; i<4; i++)
{
pinMode(sensorLEDs[i], OUTPUT);
}
pinMode(relayPort, OUTPUT);
pinMode(programmingPort, INPUT);
CorrectMelody();
}

void SaveSettings()
{
EEPROM.write(1,TASK_DIFFICULTY);
}
boolean ReadSensor(byte sensorId)
{
int val = analogRead(sensors[sensorId]);
//Serial.print(" SENSOR [");
//Serial.print(sensorId);
//Serial.print("]=");
//Serial.println(val);
return val>MIN_SENSOR_VALUE;
}

// reading
byte GetCurrentCode()
{
byte res=0;
for(int i=1; i<5; i++)
{
if(ReadSensor(i-1))
res+=i;
}

if(res>4)
res=0;

return res;
}

void CheckProgrammingMode()
{
if(digitalRead(programmingPort)==HIGH)
{
if(IsProgrammingMode)
{
// Stop the programming
IsProgrammingMode=false;
SetSensorLEDs(LOW);
SaveSettings();
Init();
ShowProgress(0);
CloseDoor();
}else
{
IsProgrammingMode=true;
SetSensorLEDs(HIGH);
// TODO: Зажечь все светодиоды и подсветить текущий уровень сложности
}

delay(1000);
}
}

void TurnOnSensorLED(byte id)


{
digitalWrite(sensorLEDs[id], LOW);
}

// indicate the shot


void SetSensorLEDs(int level)
{
for(byte i=0; i<4; i++)
if(level==LOW)
digitalWrite(sensorLEDs[i], HIGH);
else
digitalWrite(sensorLEDs[i], LOW);
}

void ShowProgress(byte progress)


{
for(byte i=0; i<MAX_TASK_DIFFICULTY; i++)
{
if(i<progress)
digitalWrite(progressLEDs[i], HIGH);
else
digitalWrite(progressLEDs[i], LOW);
}
}

void SimpleMelody(byte thisNote)


{

int noteDuration = 1000/noteDurations1[thisNote];


tone(tonePort, melody1[thisNote],noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(tonePort);

}
void CorrectMelody()
{
for (int thisNote = 0; thisNote < 1; thisNote++) {
int noteDuration = 1000/noteDurations1[thisNote];
tone(tonePort, melody1[thisNote],noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(tonePort);
}
}

void WrongMelody()
{
for (int thisNote = 0; thisNote < 2; thisNote++) {
int noteDuration = 1000/noteDurations2[thisNote];
tone(tonePort, melody2[thisNote],noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(tonePort);
}
}

void OpenDoor()
{
digitalWrite(relayPort, HIGH);
}

void CloseDoor()
{
digitalWrite(relayPort, LOW);
}

void setup() {
//Serial.begin(9600);
Init();
OpenDoor();
SetSensorLEDs(HIGH);
ShowProgress(16);

delay(500);
SetSensorLEDs(LOW);
ShowProgress(0);
CloseDoor();
//Serial.println("--- INIT COMPLETE ---");
}

void loop() {

CheckProgrammingMode();

//Serial.print("IsProgramming = ");
//Serial.println(IsProgrammingMode);

byte code = GetCurrentCode();

if(IsProgrammingMode)
{
//Serial.print("TASK_DIFFICULTY = ");
//Serial.println(TASK_DIFFICULTY);

if(code==1||code==2)
{
if(TASK_DIFFICULTY<MAX_TASK_DIFFICULTY)
{
TASK_DIFFICULTY+=1;
//ShowProgress(TASK_DIFFICULTY);
SimpleMelody(0);
delay(200);
}
}
if(code==3||code==4)
{
if(TASK_DIFFICULTY>MIN_TASK_DIFFICULTY)
{
TASK_DIFFICULTY-=1;
//ShowProgress(TASK_DIFFICULTY);
SimpleMelody(2);
delay(200);
}
}

ShowProgress(TASK_DIFFICULTY);
return;
}

// Serial.print("PrevCode = ");
// Serial.print(currentCode);
// Serial.print(" CurrCode = ");
// Serial.print(code);
// Serial.print(" RquredCode = ");
// Serial.print(task[progress]);
// Serial.print(" Progress = ");
// Serial.println(progress);

if(isTheEnd)
{
progress+=1;
if(progress>MAX_TASK_DIFFICULTY)
{
progress= -MAX_TASK_DIFFICULTY+1;
}
SetSensorLEDs(LOW);
byte led = abs(progress%4);

if(led==2)
led=3;
else
if(led==3)
led=2;

TurnOnSensorLED(led);
byte res = abs(progress);
ShowProgress(res);

delay(100);
return;
}

if(currentCode!=code && code!=0)


{
SetSensorLEDs(LOW);
TurnOnSensorLED(code-1);

if(code==task[progress])
{
currentCode=code;
progress+=1;
ShowProgress(progress);
CorrectMelody();

if(progress>=TASK_DIFFICULTY)
{
CorrectMelody();
CorrectMelody();
CorrectMelody();
isTheEnd=true;
OpenDoor();
}

}
else
{
isTheEnd=false;
progress=0;
ShowProgress(progress);
currentCode=0;
SetSensorLEDs(LOW);
WrongMelody();
}
}

169) Arduino Remote Controlled Car Projet


COMPONENTS AND SUPPLIES

Servos (Tower Pro MG996R)


× 5
5 servos were used on the car
Arduino UNO & Genuino UNO
Arduino UNO and Arduino USB
× 1
host shield were used

Relay (generic)
2 Channel really board was used × 1
to control the motor
Slide Switch
Power on/off switches
× 2
9V battery (generic)
9v Battery holder × 1

4xAA battery holder


with 4 AA batteries

ABOUT THIS PROJECT


This project was built for a competition, to compete against similarly
designed cars. It had to navigate a course, then pick up a half a pound
weight carry it up a thirty degree incline.
Once at the top, the weight was set in a cup across a ten inch gap. The car
then had to pick up another weight across the gap and transport it back
down the incline and drop it off. The car had to then maneuver back
through the course to the finish.
Overall, the car performed really well. The chassie was built using some
sheet and angle aluminum. The drivetrain consisted of tank style steering.
The drive servos chosen were tower pro mg995 because of metal gearing
and high torque. Wheels for the car were designed in Creo and were 3D
rapid prototyped. The main crane arm was also 3D rapid prototyped. Both
the crane and stabilizing arm were made of carbon fiber. At the end of the
crane fork there was a very small wire used to pick the weight up. The
stabilizing arm was used to make sure the car didn't flip forward when the
weight was being deposited or picked up from across the gap.
A Hitech 311 servo was fastened to the stabilizing arm. For the electronics
and controls, a wireless Play Station 3 controller was chosen, that
connected to a Bluetooth dongle. The dongle was then connected to the
Arduino USB host shield, which was stacked on a regular Arduino UNO.
Once code was created, the driver servos and the stabilizer servo could be
controlled directly from the ports of the Arduino USB Host shield. The
crane was controlled by a Hitech mg485 servo that had been modified to
be a DC motor. The motor was controlled by a two-channel relay board.
The Arduino USB host shield sent a signal to the relay board to tell it
when to send power to the motor, and in what direction.
After the car was designed, assembled, and some of the kinks were
worked out, it was ready for competition. The car performed very well on
the day of competition, posting the fastest time to complete the course. I
would like to think my team members for their time and hard work (Darrin
Small, Glen Smith, Lauren Toma, Alex Yoon, Dmytro Zaytsev, and
Ximin Zhao).
SCHEMATICS

This is the schematic for all of the electronics. Its kind of complicated
in the center of the diagram, however the bluetooth dongle receives
what the PS3 controller is telling it and it sends it through the Arduino
USB host shield that is plug in to the Arduino UNO which tells
everything else that to do.
CODE

#include <PS3BT.h> //Include the necessary libraries.


#include <Servo.h>

USB Usb;
BTD Btd(&Usb);
PS3BT PS3(&Btd);

Servo servo1; //Create instances of type Servo. servo1


and servo2 are drive servos. servo3 is for the stabalizer.
Servo servo2;
Servo servo3;

int position=90;

void setup()
{
Serial.begin(115200);
if (Usb.Init() == -1)
{
Serial.print(F("\r\nOSC did not start"));
while(1); //halt
}
Serial.print(F("\r\nPS3 Bluetooth Library Started"));

servo1.attach(5); //Drive servo1 and servo2


servo2.attach(3);
servo3.attach(6); //Crane arm on servo3
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
}
void loop()
{
Usb.Task();

if(PS3.PS3Connected || PS3.PS3NavigationConnected) //Drive code


{

servo1.write(map(PS3.getAnalogHat(RightHatY), 0, 255, 0, 165));


servo2.write(map(PS3.getAnalogHat(LeftHatY), 0, 255, 180, 15));

if(PS3.getButtonPress(DOWN) && position<178) //servo3 for stabilization


drive out. the in and out need to be teste dto make sure everything goes the correct way.
{
servo3.write(position++);
delay(10);
}

if(PS3.getButtonPress(UP) && position>3) //servo3 drive in


{
servo3.write(position--);
delay(10);
}

if(PS3.getButtonPress(X)) //DC drive out. Needs limiting factrs for


crane and testing with the shield
{ digitalWrite(7,HIGH);
delay(10);
}
else
{ digitalWrite(7,LOW);
}

if(PS3.getButtonPress(TRIANGLE)) //DC drive in.


{ digitalWrite(8,HIGH);
delay(10);
}
else
{ digitalWrite(8,LOW);
}
}
}

170) Arduino Wooden Chest Air Quality Monitor Projet

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO
× 1

DHT11 Temperature & Humidity


Sensor (4 pins)
× 1

PHPoC Shield for Arduino

× 1

Adafruit CCS811 Air Quality


Sensor Breakout - VOC and eCO2 × 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


A project completed to measure the air condition in a diesel polluted
building. Then the final design enclosed in a wooden box to demonstrate
its function to apprentices for inspiration for their projects.

testing
testing sensitivity to fumes using a permanent marker pen
running off batteries
new home
glue plus alterations
almost done

SCHEMATICS
CODE

//***************************************************************************
// This is a library for the CCS811 air

// These sensors use I2C to communicate. The device's I2C address is 0x5A
#include <SD.h> // sd card
#include <Wire.h>
#include "RTClib.h" // real time clock
#include <DHT.h> // load lib dht11
#include "Adafruit_CCS811.h"
#include "Arduino.h"
#include "LiquidCrystal_PCF8574.h"

#define LCD_ADDRESS 0x27 // Define LCD characteristics


#define LCD_ROWS 4
#define LCD_COLUMNS 20
#define SCROLL_DELAY 150
#define BACKLIGHT 255 // object initialization
#define dht_apin 2
#define dht_type DHT11

int n = 1;
int val; // A simple data logger for the Arduino analog pins

#define LOG_INTERVAL 1000 // mills between entries (reduce to take more/faster data)

// how many milliseconds before writing the logged data permanently to disk
// set it to the LOG_INTERVAL to write each time (safest)
// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to
// the last 10 reads if power is lost but it uses less power and is much faster!

#define SYNC_INTERVAL 10000 // mills between calls to flush() - to write data to the card
600000 = 10 minutes
uint32_t syncTime = 0; // time of last sync()

RTC_DS1307 RTC; // define the Real Time Clock object

const int chipSelect = 10; // for the data logging shield, we use digital pin
10 for the SD cs line

DHT dht(dht_apin, dht_type); // sensor pin S to pin11

LiquidCrystal_PCF8574 lcdI2C;
Adafruit_CCS811 ccs;

File logfile;
void error(char *str)
{
Serial.print(F("error: "));
Serial.println(str);
}

void setup() {

Serial.begin(9600);

// initialize the SD card


Serial.print(F("Initializing SD card..."));
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);

// see if the card is present and can be initialized:


if (!SD.begin(chipSelect)) {
error("Card failed, or not present");
}
Serial.println(F("card initialized."));

// create a new file


char filename[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}

if (! logfile) {
error("couldnt create file");
}

Serial.print(F("Logging to: "));


Serial.println(filename);

// connect to RTC
Wire.begin();
if (!RTC.begin()) {
logfile.println("RTC failed");
#if ECHO_TO_SERIAL
Serial.println(F("RTC failed"));
#endif //ECHO_TO_SERIAL
}

logfile.println("datetime,co2 ,tvoc ,Humidity ,Temperature ");


//#if ECHO_TO_SERIAL
// Serial.println("..........,......,datetime,.....,......,......");
//#endif //ECHO_TO_SERIAL

// If you want to set the aref to something other than 5v


analogReference(EXTERNAL);
lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT);
Serial.println(F("CCS811 test"));
lcdI2C.print(" CCS811 test" );
lcdI2C.setCursor (0,1);
lcdI2C.print(" warming up" );
lcdI2C.setCursor (0,2);
lcdI2C.print("data logger file No." );
lcdI2C.setCursor (0,3);
lcdI2C.println(filename);
if(!ccs.begin()){
Serial.println(F("Failed to start sensor! Please check your wiring."));
while(1);
}
//calibrate temperature sensor
while(!ccs.available());
float temp = ccs.calculateTemperature();
ccs.setTempOffset(temp - 25.0);

delay(10000); // wait for 10 seconds


lcdI2C.clear(); // Clear LCD screen.

void loop() {
float h = dht.readHumidity();
float f = dht.readTemperature();
if(ccs.available()){
float temp = ccs.calculateTemperature();
if(!ccs.readData()){

DateTime now;
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); // delay for the amount of
time we want between readings

now = RTC.now(); // fetch the time

int H = now.hour(); // Get the hours right now and store them in an integer called h
int M = now.minute(); // Get the minutes right now and store them in an integer called m
int S = now.second(); // Get the seconds right now and store them in an integer called s

logfile.print(now.year(), DEC);
logfile.print("/");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print(" ");
if (H<10){ // Add a zero, if necessary, as above
logfile.print(0);
}
logfile.print(now.hour(), DEC);
logfile.print(":");
if (M<10){ // Add a zero, if necessary, as above
logfile.print(0);
}
logfile.print(now.minute(), DEC);
logfile.print(":");
if (S<10){ // Add a zero, if necessary, as above
logfile.print(0);
}
logfile.print(now.second(), DEC);
logfile.print('"');
Serial.print('"');
Serial.print(now.year(), DEC);
Serial.print("/");
Serial.print(now.month(), DEC);
Serial.print("/");
Serial.print(now.day(), DEC);
Serial.print(" ");
if (H<10){ // Add a zero, if necessary, as above
Serial.print(0);
}
Serial.print(now.hour(), DEC);
Serial.print(":");
if (M<10){ // Add a zero, if necessary, as above
Serial.print(0);
}
Serial.print(now.minute(), DEC);
Serial.print(F(":"));
if (S<10){ // Add a zero, if necessary, as above
Serial.print(0);
}
Serial.print(now.second(), DEC);
Serial.print(F(" "));
Serial.print(F("CO2: "));
Serial.print(ccs.geteCO2());
Serial.print(F("ppm, TVOC: "));
Serial.print(ccs.getTVOC());
Serial.print(F("ppb Temp:"));
Serial.println(f); // temp from dht11

lcdI2C.setCursor (0,0);
lcdI2C.print ("CO2 ");
lcdI2C.setCursor (5,0);
lcdI2C.print (" ");
lcdI2C.setCursor (5,0);
lcdI2C.print(ccs.geteCO2()); // Print print String to LCD on first line
lcdI2C.setCursor (0,1); // Set cursor at the begining of line 2
lcdI2C.print ("tVOC ");
lcdI2C.print(ccs.getTVOC()); // Print print String to LCD on second line
lcdI2C.print (" ");
lcdI2C.setCursor (12,1);
if (H<10){ // Add a zero, if necessary, as above
lcdI2C.print(0);
}
lcdI2C.print(now.hour(), DEC);
lcdI2C.print (":");
if (M<10){ // Add a zero, if necessary, as above
lcdI2C.print(0);
}
lcdI2C.print(now.minute(), DEC);
lcdI2C.print (":");
if (S<10){ // Add a zero, if necessary, as above
lcdI2C.print(0);
}
lcdI2C.print(now.second(), DEC);
lcdI2C.setCursor (0,2);
lcdI2C.print ("Humidity ="); // print on the lcd Humidity =
lcdI2C.print(h); // to print the humidity
lcdI2C.print("% "); //print "percentage" symbol
lcdI2C.setCursor (0,3);
lcdI2C.print("Temperature ="); // print on the lcd temp =
lcdI2C.print (f); // print on the lcd temperture
lcdI2C.print((char)223); // print "degrees" symbol
lcdI2C.print("C"); // print "C" with spaces after to fill 20 character line

logfile.print(", ");
logfile.print(ccs.geteCO2());
logfile.print(",");
logfile.print(ccs.getTVOC());
logfile.print(",");
logfile.print(h);
logfile.print(",");
logfile.print(f);
logfile.println();

// Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
// which uses a bunch of power and takes time
if ((millis() - syncTime) < SYNC_INTERVAL) return;
syncTime = millis();

// blink LED to show we are syncing data to the card & updating FAT!

logfile.flush();

}
else{
Serial.println(F("ERROR!"));
while(1);
}
}

}
171) Smart Lock Door with Voice Acrivation using Arduino Projet
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

SparkFun Audio-Sound Breakout -


WTV020SD
× 1

SG90 Micro-servo motor


× 1

Alphanumeric LCD, 16 x 2

× 1

5 mm LED: Red

× 1

Resistor 330 ohm

× 1

Variable Resistor 10k ohm


× 1

Custom PCB

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Solder Wire, Lead Free

Desoldering Tip, Tenma 21-8220


Desoldering Pump

Scissor, Electrician

Wire Stripper & Cutter, 18-10 AWG / 0.75-


4mm² Capacity Wires

Hot glue gun (generic)

ABOUT THIS PROJECT


This project is to creates smart lock door system with voice activation to
open and close the door using voice sensor and arduino uno. We are using
LCD and red LED for the indicator. And we are also using motor servo to
operate the door.
It means you can open or closing a door just by your clap or your voice.
The door open and close when the sensor detects a voice.
The DC motor operates the door 90 degrees to open and close the door
when the sensor detects a voice.
The LED turns on only during open door situations.
The LCD shows you the situation as the door opening or closing. When
the door is opening, it shows you "Pintu Terbuka" or "Opening the
door," and when the door is closing it show you "Pintu Tertutup" or
"Closing the door."
This project still have an imperfection that is the sensor can detect any
voice, so other people or other voice can open or close your door.

SCHEMATICS
CODE

#include <LiquidCrystal.h> //inisialisasi library LCD


#include <Servo.h> //inisialisasi library motor servo
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //inisialisasi pin LCD yang digunakan yaitu
rs=12,en=11,d4=5,d5=4,d6=3,d7=2
Servo myservo1; //inisialisasi variabel dari untuk menggerakkan motor servo
int pos = 0; //inisialisasi keadaan awal dari motor servo yaitu pos=0
int LED1=6; //inisialisasi pin LED terhubung ke pin 6 arduino
int soundSensor=8; //inisialisasi pin sensor suara terhubung ke pin 8 arduino
boolean LEDStatus=false; //inisialisasi variabel LEDStatus berupa tipe data boolean yang
memiliki nilai awal yaitu false
void setup() { //prosedur untuk setup
Serial.begin(9600); // digunakan untuk memulai komunikasi serial dengan kecepatan
transmisi data 9600 bps
pinMode(LED1, OUTPUT); //konfigurasi pin LED1 sebagai output
pinMode(soundSensor,INPUT); //konfigurasi pin sensor suara sebagai INPUT
myservo1.attach(9); //kabel data servo dihubungkan ke pin 9 arduino
int a; //inisialisasi variabel a berupa tipe data integer
lcd.begin(16,2); //menunjukkan LCD yang digunakan memiliki 16 kolom dan 2 baris
lcd.setCursor(16, 0); //untuk menentukan letak kursor pertama atau letak awal karakter pada
kolom-17 baris-1
lcd.print("Project UAS"); //menampilkan karakter "Project UAS" pada baris pertama
lcd.setCursor(16, 1); //untuk menentukan letak kursor kedua atau letak awal karakter pada
kolom-17 baris-2
lcd.print("MIKRO II"); //menampilkan karakter "MIKRO II" pada baris kedua
for(a=0;a<16;a++){ //fungsi for digunakan untuk pengulangan dengan kondisi awal variabel
a=0 hingga a<16 dengan menaikkan nilai variabel a sebesar 1
lcd.scrollDisplayLeft(); //pernyataan yang diulang adalah input yang ditampilkan pada LCD
yang bergerak ke kiri .
delay(100); //jeda waktu 100 ms
}
delay(100); //jeda waktu untuk membuat LCD dalam kondisi awal adalah 100ms
lcd.clear(); //setelah jeda waktu 100ms, tampilan LCD seperti semula atau menghapus apa
yang ditampilkan sebelumnya untuk selanjutnya menampilkan karakter selanjutnya
lcd.setCursor(16, 0); //untuk menentukan letak kursor pertama atau letak awal karakter pada
kolom-17 baris-1
lcd.print("Kelompok ????"); //menampilkan karakter "Kelompok ????" pada baris pertama
lcd.setCursor(16, 1); //untuk menentukan letak kursor kedua atau letak awal karakter pada
kolom-17 baris-2
lcd.print("TKK_4_C"); //menampilkan karakter "TKK_4_C" pada baris kedua
for(a=0;a<16;a++){ //fungsi for digunakan untuk pengulangan dengan kondisi awal variabel
a=0 hingga a<16 dengan menaikkan nilai variabel a sebesar 1
lcd.scrollDisplayLeft(); //pernyataan yang diulang adalah input yang ditampilkan pada LCD
yang bergerak ke kiri .
delay(100); //jeda waktu 100ms
}
delay(100); //jeda waktu untuk membuat LCD dalam kondisi awal adalah 100ms
lcd.clear(); //setelah jeda waktu 100ms, tampilan LCD seperti semula atau menghapus apa
yang ditampilkan sebelumnya untuk selanjutnya ditampilkan kembali dengan jeda waktu
100ms
}
void loop() { //prosedur untuk looping atau pengulangan
int a; //inisialisasi variabel a berupa tipe data integer
int SensorData=digitalRead(soundSensor); //membaca sinyal keluaran dari sensor berupa
data digital yaitu logika 1 atau 0
if(SensorData==1){ //jika hasil pembacaan berogika sama dengan 1, maka
if(LEDStatus==false){ //jika kondisi lED bernilai false
lcd.begin(16,2);
lcd.setCursor(16,0); //penentuan letak kursor pada baris pertama
lcd.print("Pintu Tertutup"); //menampilkan karakter "Pintu Tertutup" pada baris pertama
lcd.setCursor(16,1); //penentuan letak kursor pada baris kedua
lcd.print(" "); //berisi spasi pada baris kedua
for(a=0;a<16;a++){ //fungsi pengulangan untuk nilai a=0 hingga a<16, variabel a terus
bertambah
lcd.scrollDisplayLeft(); //karakter yang tampil pada LCD bergerak berjalan ke kiri
delay(100); //jeda waktu 100ms
}
LEDStatus=true; //kondisi LED sama dengan true
digitalWrite(LED1,LOW); //memberi nilai LOW pada LED1, atau lampu LED mati
for (pos = 90; pos <= 180; pos += 1) { //fungsi perulangan untuk posisi servo dari 90
derajat sampai 180 derajat dengan setiap kenaikan 1
myservo1.write(pos); //memberitahu servo untuk pergi ke posisi 'pos'
delay(50); //jeda waktu 50ms
Serial.print("on"); //menampilkan karakter "on" pada serial monitor
Serial.println("");
}
}
else{ //jika salah, maka
lcd.begin(16,2);
lcd.setCursor(16,0); //penentuan letak kursor pada baris pertama
lcd.print("Pintu Terbuka"); //menampilkan karakter "Pintu Terbuka" pada baris pertama
lcd.setCursor(16,1); //penentuan letak kursor pada baris kedua
lcd.print(" "); //berisi spasi pada baris kedua
for(a=0;a<16;a++){ //fungsi pengulangan untuk nilai a=0 hingga a<16, variabel a terus
bertambah
lcd.scrollDisplayLeft(); //karakter yang tampil pada LCD bergerak berjalan ke kiri
delay(100); //jeda waktu 100ms
}
LEDStatus=false; //kondisi LED sama dengan false
digitalWrite(LED1,HIGH); //memberi nilai HIGH pada LED1, atau lampu LED nyala
for (pos = 180; pos >= 90; pos -= 1) { //fungsi perulangan untuk posisi servo dari 180
derajat sampai 90 derajat dengan setiap penurunan 1
myservo1.write(pos); //memberitahu servo untuk pergi ke posisi 'pos'
delay(50); //jeda waktu 50ms
Serial.print("off"); //menampilkan karakter "off" pada serial monitor
Serial.println("");
}
}
}
}
172) Control Chrismas Lights with Voice Commands using Arduino
Projet
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

1Sheeld

× 1

1Sheeld
× 1

Apple iPhone

× 1

RobotGeek Relay

× 2

Christmas tree
× 1

Christmas LED strip


× 1

Jumper wires (generic)

× 8

9V battery (generic)

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

OpenBuilds Drill Taps


APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Every year I buy the Christmas tree and the LED strips and just plug
the Strip to the AC socket and leave it just shuffle. This year I decided
to hack into the LED strips and start controlling it with Arduino and the
Amazing 1Sheeld Voice Recognition shield.
The LED Control
I bought a small $5 tree and the normal Christmas 2$ LED strip.
The LED strip comes with a box having a push button it's used to
shuffle between the light 8 modes.
I get the screw driver and open up this box to hack the circuit inside.
The Circuit
The circuit mainly composed of 4 PCR406 transistors to operate 4 LED
Strips and connected to the HN803A to control the signals goes out to
transistors.
Now I decide to control both it's power and it's shuffling push button so
I connect 4 jumpers to the power terminals and to the shuffle button
and reconnect them to the relay board and start controlling them using
the Arduino and 1Sheeld.
1Sheeld is a platform for Arduino that allows you to tap into your
smartphone's sensors and capabilities and let you use them in your
Arduino projects.
Basically, it is a hardware shield that sits on top of your Arduino board
and communicates over Bluetooth to this Android app, to transfer data
between it and your smartphone. You can check the getting
started tutorial on 1Sheeld website which will take you step by step till
you can operate the 1Sheeld very smoothly and it's an awesome
reference for great Arduino projects.
Voice Recognition
In this project I have used it's amazing Voice Recognition shield:
Mainly I used it to turn on and off the whole system also to shuffle
between it's 8 modes just with voice commands which are:
Waves
Sequential
Slo-glo
Chasing
Fade
Twinkle
Steady
Combination

SCHEMATICS
CODE

#define CUSTOM_SETTINGS
#define INCLUDE_VOICE_RECOGNIZER_SHIELD

#include <OneSheeld.h>

/* Voice commands set by the user. */


const char poweronCommand[] = "turn on";
const char poweroffCommand[] = "turn off";
const char combinationCommand[] = "combination";
const char wavesCommand[] = "waves";
const char sequentialCommand[] = "sequential";
const char slowCommand[] = "slow";
const char chasingCommand[] = "chasing";
const char fadeCommand[] = "fade";
const char twinkleCommand[] = "twinkle";
const char steadyCommand[] = "steady";

int lamp = 12;


int power = 11;

int counter=0;
int x=0;
int y=0;
int z=0;
int l=0;
int m=0;
int n=0;
int p=0;
int q=0;
int val=0;

void setup()
{
/* Start Communication. */
OneSheeld.begin();

pinMode(lamp,OUTPUT);
pinMode(power,OUTPUT);
}
void loop ()
{
/* Check if new command received. */
if(VoiceRecognition.isNewCommandReceived())
{
/* Compare the Poer on command. */
if(!strcmp(poweronCommand,VoiceRecognition.getLastCommand()))
{
digitalWrite(power,LOW);
counter=0;
}
/* Compare the Poer off command. */ else if
(!strcmp(poweroffCommand,VoiceRecognition.getLastCommand()))
{
digitalWrite(power,HIGH);
}
/* Compare the combination command. */
else if (!strcmp(combinationCommand,VoiceRecognition.getLastCommand()))
{
x=0-counter;
if(x<0){
x+=8;
}
for(val=0 ; val<x ; val++){
mode();
}
counter=0;

}
/* Compare the waves command. */
else if (!strcmp(wavesCommand,VoiceRecognition.getLastCommand()))
{
y=1-counter;
if(y<0){
y+=8;
}
for(val=0 ; val<y ; val++){
mode();
}
counter=1;
}
/* Compare the sequential command. */
else if (!strcmp(sequentialCommand,VoiceRecognition.getLastCommand()))
{
z=2-counter;
if(z<0){
z+=8;
}
for(val=0 ; val<z ; val++){
mode();
}
counter=2;
}
/* Compare the slow command. */
else if (!strcmp(slowCommand,VoiceRecognition.getLastCommand()))
{
l=3-counter;
if(l<0){
l+=8;
}
for(val=0 ; val<l ; val++){
mode();
}
counter=3;
}
/* Compare the chasing command. */
else if (!strcmp(chasingCommand,VoiceRecognition.getLastCommand()))
{
m=4-counter;
if(m<0){
m+=8;
}
for(val=0 ; val<m ; val++){
mode();
}
counter=4;
}
/* Compare the fade command. */
else if (!strcmp(fadeCommand,VoiceRecognition.getLastCommand()))
{
n=5-counter;
if(n<0){
n+=8;
}
for(val=0 ; val<n ; val++){
mode();
}
counter=5;
}
/* Compare the Twinkle command. */
else if (!strcmp(twinkleCommand,VoiceRecognition.getLastCommand()))
{
p=6-counter;
if(p<0){
p+=8;
}
for(val=0 ; val<p ; val++){

mode();
}
counter=6;
}
/* Compare the steady command. */
else if (!strcmp(steadyCommand,VoiceRecognition.getLastCommand()))
{
q=7-counter;
if(q<0){
q+=8;
}
for(val=0 ; val<q ; val++){
mode();
}
counter=7;
}
}
}

void mode(){
digitalWrite(lamp,LOW);
delay(150);
digitalWrite(lamp,HIGH);
delay(150);
}
173) Arduino Interactive LED Name Projet

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1
Slide Switch

× 1

LED (generic)

× 36

SparkFun Rocker Switch


× 1

SparkFun Potentiometer
× 2

SparkFun Toggle Switch


× 1

SparkFun Button
× 1

SparkFun Shift Register -


SN74HC595 × 5

SparkFun Triple Axis


Accelerometer Breakout - LIS3DH
× 1

SparkFun Piezo Alarm


× 1
Breadboard (generic)

× 2

Resistor 330 ohm

× 36
NECESSARY TOOLS AND MACHINES
Laser cutter (generic)

Soldering iron (generic)


APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Our project is meant to be an interactive toy for children that can be
customized to put any child's name on it. The name can blink, light up like
a color wave, and loop through each letter individually at a certain pace.
We decided to make this project because we thought that children would
enjoy colorful lights that spell out their name and light up in a few
different patterns to avoid getting bored of it too quickly. This project was
also a challenge on the physical building and programming side which
made it that much more interesting!
Tutorial
Set up the shift registers on a breadboard with 1-2 spaces between each,
and follow this fritzing diagram to properly daisy chain and connect
them to the arduino.
Diagram of daisy chained shift registers
Add the accelerometer to the end of the breadboard where there is space
and follow this hookup guide to wire it up, only wire the four left wires
in the diagram because that is all that's needed (Don't forget that this
accelerometer can only take 3.3V otherwise it can be damaged):
Connect the piezo alarm's small lead to a potentiometer that will control
the volume and connect the longer lead to digital pin 9 on the arduino.
Get the second breadboard and use resistors to link each shift register
pin for each LED. I recommend taping the breadboards to the bottom
side of the enclosure to prevent movement of the resistors.
Result after connecting breadboards with resistors and connecting the
accelerometer (top right)
When you get your cutout for your enclosure, place the LED diodes
through the holes with the short lead facing either right or left, but make
sure that all the LEDs are put in the same way. Then, bend them about
45 degrees to make soldering easier. Solder the negative lead (short
one) to the next closest negative lead and do this for all LEDs, so that
they are all connected. Then solder a piece of wire (preferably black)
that can reach the arduino's ground pin when inside the finished
product.
Cut wire that is long enough that can reach the breadboard from the
LEDs depending on how tall your enclosure is and solder the wire to
the longer lead of each LED and repeat until all LEDs have a wire
attached. Test by connecting the LEDs to their appropriate pin on the
breadboard and connecting the grounding wire to see if they all turn on,
if any of them don't turn on then fix the connections that you previously
soldered.
Result after wire is soldered to each LED
Place the buttons/switches into their appropriate sockets/holes and
solder wire to them that is long enough to reach the Arduino.
When you are ready to attach the wires from the LED to the breadboard
follow this diagram that shows where each wire should go.

When complete squish all the components together and use wood glue
to close the box and connect a 9V battery to the Arduino as a power
supply.

Finished project

SCHEMATICS
CODE

#include <SoftReset.h>

#include <SparkFunLIS3DH.h>
#include <Wire.h>
#include <SPI.h>

//Pin connected to ST_CP of 74HC595


int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

int j = 0;
int mode = 0;
int blinkBtn = 4;
int waveBtn = 2;
int loopBtn = 3;
int masterSwitch = 5;
int blinkBtnState, waveBtnState, loopBtnState, masterState;
int speedPot = A0;
int speedValue = 0;
int master = 0;
int buzzer = 9;
LIS3DH myIMU;
int reset = 6;
//holders for infromation you're going to pass to shifting function
byte waveOne, waveTwo, waveThree, waveFour, waveFive, loopOne, loopTwo, loopThree,
loopFour, loopFive;
byte waveDataOne[16], waveDataTwo[16], waveDataThree[16], waveDataFour[16],
waveDataFive[16];
byte loopDataOne[10], loopDataTwo[10], loopDataThree[10], loopDataFour[10],
loopDataFive[10];

void setup() {
digitalWrite(reset, HIGH);
delay(200);
pinMode(reset, OUTPUT);

//set pins to output because they are addressed in the main loop
pinMode(latchPin, OUTPUT);
pinMode(blinkBtn, INPUT_PULLUP);
pinMode(waveBtn, INPUT_PULLUP);
pinMode(loopBtn, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
pinMode(masterSwitch, INPUT_PULLUP);
myIMU.begin();
Serial.begin(9600);
MCUSR = 0;
loopDataOne[0] = 1;
loopDataOne[1] = 3;
loopDataOne[2] = 6;
loopDataOne[3] = 12;
loopDataOne[4] = 24;
loopDataOne[5] = 48;
loopDataOne[6] = 96;
loopDataOne[7] = 192;
loopDataOne[8] = 128;
loopDataOne[9] = 0;

loopDataTwo[0] = 2;
loopDataTwo[1] = 6;
loopDataTwo[2] = 12;
loopDataTwo[3] = 24;
loopDataTwo[4] = 48;
loopDataTwo[5] = 96;
loopDataTwo[6] = 192;
loopDataTwo[7] = 128;
loopDataTwo[8] = 1;
loopDataTwo[9] = 1;

loopDataThree[0] = 8;
loopDataThree[1] = 24;
loopDataThree[2] = 48;
loopDataThree[3] = 96;
loopDataThree[4] = 192;
loopDataThree[5] = 128;
loopDataThree[6] = 0;
loopDataThree[7] = 1;
loopDataThree[8] = 3;
loopDataThree[9] = 6;

loopDataFour[0] = 4;
loopDataFour[1] = 12;
loopDataFour[2] = 24;
loopDataFour[3] = 48;
loopDataFour[4] = 224;
loopDataFour[5] = 193;
loopDataFour[6] = 3;
loopDataFour[7] = 2;
loopDataFour[8] = 2;
loopDataFour[9] = 2;

loopDataFive[0] = 0;
loopDataFive[1] = 0;
loopDataFive[2] = 0;
loopDataFive[3] = 0;
loopDataFive[4] = 0;
loopDataFive[5] = 1;
loopDataFive[6] = 3;
loopDataFive[7] = 6;
loopDataFive[8] = 12;
loopDataFive[9] = 8;

waveDataOne[0] = 56;
waveDataOne[1] = 124;
waveDataOne[2] = 198;
waveDataOne[3] = 131;
waveDataOne[4] = 1;
waveDataOne[5] = 0;
waveDataOne[6] = 0;
waveDataOne[7] = 0;
waveDataOne[8] = 0;
waveDataOne[9] = 0;
waveDataOne[10] = 0;
waveDataOne[11] = 0;
waveDataOne[12] = 0;
waveDataOne[13] = 0;
waveDataOne[14] = 0;
waveDataOne[15] = 0;

waveDataTwo[0] = 0;
waveDataTwo[1] = 0;
waveDataTwo[2] = 0;
waveDataTwo[3] = 1;
waveDataTwo[4] = 25;
waveDataTwo[5] = 60;
waveDataTwo[6] = 102;
waveDataTwo[7] = 194;
waveDataTwo[8] = 128;
waveDataTwo[9] = 0;
waveDataTwo[10] = 0;
waveDataTwo[11] = 0;
waveDataTwo[12] = 0;
waveDataTwo[13] = 0;
waveDataTwo[14] = 0;
waveDataTwo[15] = 0;

waveDataThree[0] = 0;
waveDataThree[1] = 0;
waveDataThree[2] = 0;
waveDataThree[3] = 0;
waveDataThree[4] = 0;
waveDataThree[5] = 0;
waveDataThree[6] = 0;
waveDataThree[7] = 4;
waveDataThree[8] = 7;
waveDataThree[9] = 251;
waveDataThree[10] = 248;
waveDataThree[11] = 0;
waveDataThree[12] = 0;
waveDataThree[13] = 0;
waveDataThree[14] = 0;
waveDataThree[15] = 0;

waveDataFour[0] = 0;
waveDataFour[1] = 0;
waveDataFour[2] = 0;
waveDataFour[3] = 0;
waveDataFour[4] = 0;
waveDataFour[5] = 0;
waveDataFour[6] = 0;
waveDataFour[7] = 0;
waveDataFour[8] = 0;
waveDataFour[9] = 0;
waveDataFour[10] = 1;
waveDataFour[11] = 3;
waveDataFour[12] = 114;
waveDataFour[13] = 248;
waveDataFour[14] = 140;
waveDataFour[15] = 4;

waveDataFive[0] = 0;
waveDataFive[1] = 0;
waveDataFive[2] = 0;
waveDataFive[3] = 0;
waveDataFive[4] = 0;
waveDataFive[5] = 0;
waveDataFive[6] = 0;
waveDataFive[7] = 0;
waveDataFive[8] = 0;
waveDataFive[9] = 0;
waveDataFive[10] = 0;
waveDataFive[11] = 0;
waveDataFive[12] = 3;
waveDataFive[13] = 4;
waveDataFive[14] = 12;
waveDataFive[15] = 8;
}

void loop() {
//Read button states and analog value
blinkBtnState = digitalRead(blinkBtn);
waveBtnState = digitalRead(waveBtn);
loopBtnState = digitalRead(loopBtn);
masterState = digitalRead(masterSwitch);
speedValue = analogRead(speedPot);

speedValue = speedValue / 3;
Serial.println(speedValue);
//Prevents lights from flashing too fast to avoid epilepsy
if(speedValue < 30)
speedValue = 30;

//Checks if button is clicked and then changes mode appropriately


if(masterState == LOW)
{
master = 1;
}
else
{
master = 0;
turnOff();
digitalWrite(reset, LOW);
}
if(blinkBtnState == LOW)
{
mode = 1;
}
if(waveBtnState == LOW)
{
mode = 2;
}
if(loopBtnState == LOW)
{
mode = 3;
}

//Beeps at a certain frequency when enclosure is rotated too much


if(myIMU.readFloatAccelX() > 0.5 || myIMU.readFloatAccelX() < -0.5 ||
myIMU.readFloatAccelY() > 0.5 || myIMU.readFloatAccelY() < -0.5)
{
tone(buzzer,350,100);
}

//Runs led modes based on current mode


if(mode == 1 && master == 1)
{
if(speedValue < 150)
speedValue = 150;
blinkLeds(speedValue);
}
if(mode == 2 && master == 1)
{
colorWave(speedValue);
}
if(mode == 3 && master == 1)
{
loopLetters(speedValue);
}
}

//LEDs light up by columns, two at a time from left to right


void colorWave(int d)
{
if(j==16)
j=0;
waveOne = waveDataOne[j];
waveTwo = waveDataTwo[j];
waveThree = waveDataThree[j];
waveFour = waveDataFour[j];
waveFive = waveDataFive[j];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, waveFive);
shiftOut(dataPin, clockPin, waveFour);
shiftOut(dataPin, clockPin, waveThree);
shiftOut(dataPin, clockPin, waveTwo);
shiftOut(dataPin, clockPin, waveOne);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
j++;
delay(d);
}

//LEDs make a trail and loop each letter individually


void loopLetters(int d)
{
if(j==10)
j=0;
loopOne = loopDataOne[j];
loopTwo = loopDataTwo[j];
loopThree = loopDataThree[j];
loopFour = loopDataFour[j];
loopFive = loopDataFive[j];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, loopFive);
shiftOut(dataPin, clockPin, loopFour);
shiftOut(dataPin, clockPin, loopThree);
shiftOut(dataPin, clockPin, loopTwo);
shiftOut(dataPin, clockPin, loopOne);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
j++;
delay(d);
}

void turnOff()
{
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
}

//blinks the whole register based on the number of times you want to
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkLeds(int d)
{
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
digitalWrite(latchPin, 1);
delay(d);
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(d);
}

// the heart of the program


void shiftOut(int myDataPin, int myClockPin, byte myDataOut)
{
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low

//internal function setup


int i=0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);

//clear everything out just in case to


//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);

//for each bit in the byte myDataOut�


//NOTICE THAT WE ARE COUNTING DOWN in our for loop
//This means that %00000001 or "1" will go through such
//that it will be pin Q0 that lights.
for (i=7; i>=0; i--)
{
digitalWrite(myClockPin, 0);

//if the value passed to myDataOut and a bitmask result


// true then... so if we are at i=6 and our value is
// %11010100 it would the code compares it to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1<<i) )
{
pinState= 1;
}
else
{
pinState= 0;
}

//Sets the pin to HIGH or LOW depending on pinState


digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent bleed through
digitalWrite(myDataPin, 0);
}
//stop shifting
digitalWrite(myClockPin, 0);
}

174) Arduino Wİ-Fi Power Toogler Projet


COMPONENTS AND SUPPLIES

Arduino MKR1000

× 1

DFRobot DF Robot Lithium


Polymer Battery (1000mAh, 3.7V) × 1

Jumper wires (generic)


× 1

N-Channel Power Mosfet


(STP36NF06L) × 1

Linear Regulator (7805)

× 1

Resistor 1k ohm

× 1

Resistor 100k ohm

× 2

Resistor 221k ohm

× 1

PCB terminal block (3-way)


× 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
pushingbox

Google Sheets

ABOUT THIS PROJECT


Our Wi-Fi connection at home tends to fail 2-3 times per week. The
usual remedy is to turn the Wi-Fi router off and on again; which
normally fixes it. When we are at home this is a pain, as we have to
excavate the router from under a mass of twisted cables. When we are
out, this is not possible; which is annoying as it prevents any remote
desktoping to machines at our flat, and means any IoT devices/projects
go belly up.
This project documents the design and build of an automated Wi-Fi
power toggler which:
Detects a drop-out in the Wi-Fi internet connection
Disconnects power, waits and reconnects power to the Wi-Fi router
Automatically fills out and submits a web log-in form (required with
the internet connection we have in our apartment)
Records these drop-outs, whether the power was out during the drop-
out and whether the power-cycling restored internet access, in an
online spreadsheet.
Build Instructions
The basic steps for the build are as follows:
1) Buy/find/salvage/scavenge the necessary hardware; other that the
MKR1000 board it's mostly stuff you might have lying around.
2) Find your Wi-Fi router (it is probably under a twisted mess of cables
under a desk somewhere)
3) Check the DC wall-wart for what voltage and current it puts out.
Mine is rated to output 12V at 1A, but when I measured it with no load
attached it was outputting about 16V.
4) Provided the voltage is below 35V, and the current below about 3A
(I'd be surprised if they weren't); the hardware described in this project
should work
5) Cut the DC-jack off-of the wall-wart, leaving a few centimeters of
cable (to allow the jack to be plugged back into the Wi-Fi router later).
This is a point of no return so you might want to put the other bits
together first to check you've got it sorted. Also if there is no visible
marking, use some tape to keep track of which of the two short wires
from the DC-jack came from each of the two longer wires to the wall-
wart.

Cut the wires between the wall-wart and DC-jack (which plugs into
router). Mark one of pair with tape.
6) Use a multi-meter to check the polarity of the wires coming from the
wall-wart, and label them
7) Assemble the circuit as indicated on the schematic on the hardware
page. PCB header terminals like these, are a good way of connecting
the larger wires from the wall-wart and to the DC-jack onto the
breadboard.
8) Customize the Arduino script (see below and the software page for
details) to have the details of your Wi-Fi connection, etc. and then
upload it to the MKR1000 board.
9) Turn on the wall-wart and enjoy never having to manually power-
cycle your router ever again! And also have the satisfaction of a record
being kept of the number of times this power-cycling has been
necessary!
Customizing the Arduino Code
The hardware and software sections provide details of the hardware
required, and the software which needs to be programmed onto the
MKR1000 board. There are two additional steps that are required to get
the full functionality.
The first is setting up a Google Form, and PushingBox account to allow
the Arduino to report information about connection drop-outs and
recoveries. For this project I have followed the excellent
instructions here. There are quite a few steps, but if you follow them
carefully you should get a PushingBox 'DeviceID' which you can paste
into the Arduino sketch, and 'hey-presto' your Ardunio can upload stuff
into a google docs spreadsheet.
The second is log-in details which may be required for your ISP (we
have such a requirement in our apartment). To find these details, go to
the landing page where you normally enter your login information. A
screenshot of our log-in page is given below:
Web Login Page for our Internet
You then need to navigate to the source code of this page (most
browsers will have an option to do so under the 'View' or 'Tools' menu).
You are looking for the action which is taken when you submit the
form (click the login button). The image below shows the source code
for our landing page:

Source Code for Web Login Landing Page


Highlighted in the above source code are the action which is taken
when the web login form is submitted (in this case an HTTP POST to
login.spirit.com.au/login), and also the fields which are passed as part
of this POST (namely 'username' and 'password').
Depending what you find you may need to modify the Arduino code a
little beyond the section I've highlighted for editing, but if it's a similar
set-up you simply need to replace the:
char serverLogin[] = "login.your.isp.name";
With an appropriate host name (in above example
"login.spirit.com.au"), and the:
char loginSubPage[] = "/login";
With an appropriate URL extension (in the above example it is indeed
just "/login"). As well as entering your landing page username and
password.
A Word of Warning
If you include a 3.7V Li-Po battery in your version of this project you
need to be careful about the heat dissipation in the linear regulator. I
found that without a battery being charged the MKR1000 drew only
about 20mA, so the dissipation in the linear regulator is about (16V in -
5V out) x 0.02A = 0.22W. The total thermal resistance between the
junction and ambient for the TO-220 package from the data-sheet is
about 55 degrees C / W; so this will cause a temperature rise of about
10 degrees C (just noticeable).
However, when the battery was connected and charging at the same
time, the MKR1000 drew about 200mA, this will cause a temperature
rise of around 100 degrees C, which on top of an ambient of 20 degrees
C is only just within the maximum ratings for the device. If you are
going to include a battery and allow it to be charged from the 5V
regulated supply I would recommend fitting a decent heat-sink

SCHEMATICS
CODE

/*
WiFi Power Toggler

Circuit:
Detailed schematics can be found at the URL above.
Pin 0 connects (via 1k resistor) to the gate of power mosfet
Pin 1 connects (via 100k, 220k potential divider) to the 5V output of 7805 linear regulator
5V pin connects to output of 7805 linear regulator
GND pin connects to ground of 7805 linear regulator
3.7V Li-Po battery connects via the 2-pin JST connector

*/

#include <SPI.h>
#include <WiFi101.h>

//////////////////////////////////
///// VALUES TO BE EDITED ////////
//////////////////////////////////

// WIFI SETTINGS:
char ssid[] = "YOUR_NETWORK_NAME"; // <== Insert your network SSID (name)
HERE
char pass[] = "YOUR_WIFI_PASSWORD"; // <== Your Wi-Fi password goes here
int keyIndex = 0; // <== Your network key Index number goes here
(needed only for WEP)

// WIFI Web-Login (if Required):


char serverLogin[] = "login.your.isp.name"; // <== If you need to auto-fill a web-login
page; the root URL for that page goes here
char webLoginUsername[] = "YourUserName@YourIsp"; // <== Username for ISP web
login
char webLoginPass[] = "YOUR_WEBLOGIN_PASSWORD"; // <== Password for ISP
web
char loginSubPage[] = "/login"; // <== sub-page of web log-in host URL

// Pushing Box Settings:


char devid[] = "yourDeviceID_fromPushingBox"; // <= The device ID from Pushing Box
goes here (see https://www.hackster.io/khalidaabdulla/wi-fi-power-toggler-0ed04a)

//////////////////////////////////
////////// EDITING DONE //////////
//////////////////////////////////

int status = WL_IDLE_STATUS;


boolean connStatus = false; // to track connectivity
boolean powerOnAtDisconn = false; // to track if power was off when connection failed
int failedReconnAttempts = 0;
char tempString[50]; // used for assembling varios chracter arrays (without
resorting to Strings)
// Initialize the Wifi client library
WiFiClient client;

// Variables for google-form upload:


char postmsg[250];
char serverUpload[] = "api.pushingbox.com";

// Variables for checking internet connectivity


char serverCheck[] = "www.google.com";

// Variables for timing etc.


unsigned long lastConnectionCheck = 0; // Last time connectivity assessed, in
milliseconds
unsigned long timeConnectionFailed = 0; // Time since connection failure found,
in milliseconds
const unsigned long checkInterval = 10L * 60L * 1000L; // Delay between updates, in
milliseconds (set to 10 minutes)
const unsigned long timeOff = 20L * 1000L; // How long to turn router off for (set
to 20 seconds)
const unsigned long timeOn = 20L * 1000L; // How long to wait between turn on
and connection test (set to 20 seconds)
int nTogglesMax = 10; // Maximum number of times to attempt power
toggling

// Hardware pin definitions


int mosfetPin = 0;
int ledPin = 6; // Switch on-board LED with mosfet pin to aid debugging
int powerSense = 1; // Check for presence of mains power on this input pin

void setup() {

// Set up digital outputs (to driver mosfet, and led for debugging):
pinMode(mosfetPin, OUTPUT);
pinMode(ledPin, OUTPUT);

// Also need to turn on the mosfet (otherwise Wi-Fi set-up below won't work)
digitalWrite(mosfetPin, HIGH);
digitalWrite(ledPin, HIGH);

// Set up digital input (to measure presence of power):


pinMode(powerSense, INPUT);

//Initialize serial and wait for port to open:


Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect.
}

// check for the presence of the shield:


if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}

// attempt to connect to Wifi network:


while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);

// wait 20 seconds for connection:


delay(20000);
}
// should be connected now, so print out the status:
printWifiStatus();

// attempt web log-in in case access not currently logged in:


webLogin();
}

void loop() {
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
/*
while (client.available()) {
char c = client.read();
Serial.write(c);
}*/

// If (checkInterval/1000) seconds have passed since we last checked connection,


// then it needs to be tested again:
if (millis() - lastConnectionCheck > checkInterval) {

lastConnectionCheck = millis();
connStatus = testConnection();
if (~connStatus) {
// Connection not working; log status of mains power, and record time of outage
powerOnAtDisconn = digitalRead(powerSense);
timeConnectionFailed = millis();

// Repeatedly try to turn off power, restore power and re-test connection
// limit to maximum number of iterations to prevent excessive power toggling
// if for example www.google.com is not available for some reason
int nToggles = 0;
while(~connStatus && nToggles <= nTogglesMax) {
digitalWrite(mosfetPin, LOW);
digitalWrite(ledPin, LOW);
delay(timeOff);
digitalWrite(mosfetPin, HIGH);
digitalWrite(ledPin, HIGH);
delay(timeOn);
connStatus = testConnection();
nToggles = nToggles + 1;
}

// If we have restored connection; upload report to google docs:


if(connStatus) {
uploadMsg();
webLogin();
failedReconnAttempts = 0;
} else {
// Otherwise we will wait again till another connection check is performed
failedReconnAttempts = failedReconnAttempts + 1;
}
}
}
}

// Post message to spreadsheet via Google Form


void uploadMsg() {

if (client.connect(serverUpload, 80)) {

Serial.println("Connected to pushing box");


sprintf(tempString, "Conn restored, time since disconn [s]:%d, power on at disconn:%d,
failed reconn attempts:%d", (millis() - timeConnectionFailed)/1000, powerOnAtDisconn,
failedReconnAttempts);
sprintf(postmsg,"GET /pushingbox?devid=%s&status=%s HTTP/1.1", devid, tempString);
client.println(postmsg);
sprintf(tempString, "Host: %s", serverUpload);
client.println(tempString);
client.println("Connection: close");
client.println();

// Print output to serial to assist with debugging:


Serial.println(postmsg);
Serial.println(tempString);
Serial.println("Connection: close");
Serial.println();

delay(1000);
client.stop();

} else {
Serial.println("Failed to connect to pusshing box");
client.stop();
return;
}
}

// Test if we have internet connectivity via Wi-Fi


boolean testConnection() {
// close any connection before send a new request.
// This will free the socket on the WiFi shield
client.stop();

// if there's a successful connection:


if (client.connect(serverCheck, 80)) {
Serial.println("Able to connect to google, internet working!");
// Make HTTP GET request to double check
client.println("GET /search?q=arduino HTTP/1.1");
sprintf(tempString, "Host: %s", serverCheck);
client.println(tempString);
client.println("Connection: close");
client.println();
return true;
}
else {
// Connection not made, test failed
Serial.println("connection failed");
return false;
}
}
// Log-in to ISP Web-login page (if required)
void webLogin() {
// close any connection before send a new request.
// This will free the socket on the WiFi shield
client.stop();

// if there's a successful connection:


if (client.connect(serverLogin, 80)) {
Serial.println("Connecting to web log-in page:");

// send the HTTP POST request to log user in:


sprintf(tempString, "POST %s HTTP/1.1", loginSubPage);
client.println(tempString);

sprintf(tempString, "Host: %s", serverLogin);


client.println(tempString);
client.println("Content-Type: application/x-www-form-urlencoded");

client.println("");
sprintf(tempString, "Content-Length: %d", sizeof(webLoginUsername) +
sizeof(webLoginPass) + 19);
client.println(tempString);

sprintf(tempString, "username=%s&password=%s", webLoginUsername, webLoginPass);


client.println(tempString);

client.println("");
client.println("Connection: close");
}

else {
Serial.println("Connection to web log-in page failed");
}
}

void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// print your WiFi shield's IP address:


IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

175) Arduino Bluetooth Controlled Car Projet


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

HC-05 Bluetooth Module

× 1

SparkFun Dual H-Bridge motor


drivers L298
× 1

Battery - 18650 - 7800mAh- 3.7V


× 2

Battery Holder, 18650 x 2

× 1

9V battery (generic)

× 1

9V to Barrel Jack Connector

× 1

BO Motor - Straight - 300rpm


× 2

Jumper wires (generic)

× 1

Ball Caster Wheel


× 1

Chasis - Eg. Plastic Box Cover,


Acrylic Sheet, Metal Sheet × 1
Toggle Switch, (Off)-On

× 1
NECESSARY TOOLS AND MACHINES
Tape, Double Sided

Soldering iron (generic)

Solder Wire, Lead Free


APPS AND ONLINE SERVICES
Remote For BT-Car

Arduino IDE

ABOUT THIS PROJECT


Step 1: Assemble the circuit as shown in the schematic given below.
You can use the battery pack for powering driver circuit which I have
mentioned in the components section or you could try out some other
battery pack, but keep it mind it should deliver between 7-12V and
atleast 3500mAh. Also, use different battery/battery-packs for powering
Arduino and the Motor-Driver module, but ensure they share a common
ground. Battery is one of the most important thing in this project !
Step 2: Compile the code given below in the Arduino-IDE and hit
upload, but before that make sure you have disconnected RX of
Arduino from TX of Bluetooth Module (HC-05).
Step 3: Install the application on your Android device through a link
provided below.
Step 4: Pair your Android device and HC-05 over Bluetooth. Now,
open the app and click on Bluetooth-icon and select your device from
the list.
Step 5: Now you have gone through all the hard work ! Just sit back
and relax and use the on-screen controls available on the app to control
the car/bot. You could also change the schematic and code, and add
some servos or other actuators to it. But keep it mind as you increase
the quantity of actuators, your car/bot would demand more power from
the battery/battery-pack.
Side View of Blueooth Car
Front View of Bluetooth Car
Rear View of Bluetooth Car

SCHEMATICS
CODE

char t;
const int r1=13,r2=12,l1=11,l2=10;

void setup() {
Serial.begin(9600);
pinMode(r1,OUTPUT); //right motors forward
pinMode(r2,OUTPUT); //right motors reverse
pinMode(l1,OUTPUT); //left motors forward
pinMode(l2,OUTPUT); //left motors reverse
}

void loop() {
if(Serial.available()){
t = Serial.read();
}

if(t == 'F'){ //move forward(all motors rotate in forward direction)


digitalWrite(r1,HIGH);
digitalWrite(r2,LOW);
digitalWrite(l1,HIGH);
digitalWrite(l2,LOW);
}

else if(t == 'B'){ //move reverse (all motors rotate in reverse direction)
digitalWrite(r1,LOW);
digitalWrite(r2,HIGH);
digitalWrite(l1,LOW);
digitalWrite(l2,HIGH);
}

else if(t == 'L'){ //turn right (left side motors rotate in forward direction, right side
motors rotate in reverse direction for 100ms & stop)
digitalWrite(r1,HIGH);
digitalWrite(r2,LOW);
digitalWrite(l1,LOW);
digitalWrite(l2,HIGH);
delay(100);
t = 'S';
}

else if(t == 'R'){ //turn left (right side motors rotate in forward direction, left side motors
rotate in reverse direction for 100ms & stop)
digitalWrite(r1,LOW);
digitalWrite(r2,HIGH);
digitalWrite(l1,HIGH);
digitalWrite(l2,LOW);
delay(100);
t = 'S';
}

else if(t == 'S'){ //STOP (all motors stop)


digitalWrite(r1,LOW);
digitalWrite(r2,LOW);
digitalWrite(l1,LOW);
digitalWrite(l2,LOW);
}
delay(100);
}
176) Arduino IR Remote For DC Motors Projet
COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

Texas Instruments Dual H-Bridge


motor drivers L293D
× 1

Jumper wires (generic)


× 10
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


This concept is implemented to drive two DC motors. The MP3 player
remote is used to select the motor's speed and it's states.
In this project i used
Arduino Nano
L293D Motor Driver
2 DC Motors
TSOP
MP3 Player Remote
1. Get the value from MP3 Player remote
2. Mask higher 16bit data by 0000FF value
3. Choose the desired option by arduino
Power button is used to turn ON and OFF by even and ODD number.
Speed is increased and decreased by 10
Hardware prototype output

SCHEMATICS
CODE
#include "IRremote.h"

int receiver = 11;


int velocity1 = 100;
int velocity2 = 100;

int x;
int Power__ON = 0;

const int M1P1 = 7;


const int M1N1 = 8;

const int M2P2 = 9;


const int M2N2 = 10;

const int M1__Speed = 6;


const int M2__Speed = 5;

IRrecv irrecv(receiver);
decode_results results;

void setup()
{
Serial.begin(9600);
irrecv.enableIRIn();
pinMode(M1P1, OUTPUT);
pinMode(M1N1, OUTPUT);
pinMode(M2P2, OUTPUT);
pinMode(M2N2, OUTPUT);
pinMode(M1__Speed, OUTPUT);
pinMode(M2__Speed, OUTPUT);
}
void loop()
{
if (irrecv.decode(&results))
{
x = results.value & 0x0000ff;
Serial.println(results.value, HEX);
processIR();
irrecv.resume();
}

}
void processIR()
{
if (x == 0x1f) //previous
{
Serial.println("Motor 1 rotates forward");
digitalWrite(M1P1, HIGH);
digitalWrite(M1N1, LOW);
analogWrite(M1__Speed, velocity1);
}
else if (x == 0x57) //next
{
Serial.println("Motor 2 rotates forward");
digitalWrite(M2P2, LOW);
digitalWrite(M2N2, HIGH);
analogWrite(M2__Speed, velocity2);
}
else if (x == 0x5d) //turn on
{
Power__ON = Power__ON + 1;
int x = Power__ON % 2;
Serial.println(x);
if (x == 0)
{
Serial.println("Both Motor goes OFF");
digitalWrite(M1P1, LOW);
digitalWrite(M1N1, LOW);
digitalWrite(M1P1, LOW);
digitalWrite(M1N1, LOW);
analogWrite(M1__Speed, 0);
analogWrite(M2__Speed, 0);

}
else
{
Serial.println("Both Motor ready to run");
digitalWrite(M1P1, HIGH);
digitalWrite(M1N1, LOW);
digitalWrite(M1P1, HIGH);
digitalWrite(M1N1, LOW);
}
}
else if (x == 0x67) // vol+
{
velocity1 = velocity1 + 10;
analogWrite(M1__Speed, velocity1);
Serial.println(velocity1);
}
else if (x == 0x97) // vol-
{
velocity1 = velocity1 - 10;
analogWrite(M1__Speed, velocity1);
Serial.println(velocity1);
}
else if (x == 0xdd) //mode
{
velocity2 = velocity2 + 10;
analogWrite(M2__Speed, velocity2);
Serial.println(velocity2);
}
else if (x == 0x3d) //equ
{
velocity2 = velocity2 - 10;
analogWrite(M2__Speed, velocity2);
Serial.println(velocity2);
}
else
{
}
delay(500);
}
177) Arduino Blind Runner Alarm Speed Measuring Device Projet

COMPONENTS AND SUPPLIES


LED (generic)

× 4

Jumper wires (generic)

× 1
Arduino UNO & Genuino UNO

× 1

Ultrasonic Sensor - HC-SR04


(Generic)
× 2

Buzzer

ABOUT THIS PROJECT


We witnessed children running and hurt in the corridor in front of the
school cafeteria and making loud noises.
We created 'The Speed Measuring Device' to prevent such accidents.
SCHEMATICS

CODE
#include <Servo.h>

#define BUZZ 2
#define T1 3
#define T2 4
#define E1 5
#define E2 6
#define servoPin 9
#define LED 13

Servo servo;
float wall1, wall2;
int school = 0;

void setup()
{
Serial.begin(9600);
pinMode(BUZZ, OUTPUT);
pinMode(T1, OUTPUT);
pinMode(T2, OUTPUT);
pinMode(E1, INPUT);
pinMode(E2, INPUT);
pinMode(LED, OUTPUT);
servo.attach(servoPin);
get_dis(T1, E1);get_dis(T2, E2);get_dis(T1, E1);get_dis(T2, E2);
get_dis(T1, E1);get_dis(T2, E2);get_dis(T1, E1);get_dis(T2, E2);
Serial.println(wall1 = get_dis(T1, E1));
Serial.println(wall2 = get_dis(T2, E2));
}

void loop()
{
bool B = false;
long Time = 0;
while (1)
{
if (check_super(T1, E1, wall1) == 1)
{ B = true; Time = millis(); break; }
else if (check_super(T2, E2, wall2) == 1)
{ B = false; Time = millis(); break; }
if (check_super(T1, E1, wall1) == 2)
{ return; }
else if (check_super(T2, E2, wall2) == 2)
{ return; }
}
delay(50);
if (B)
while (1)
{
if (check_super(T2, E2, wall2) == 1)
{
Time = millis() - Time;
break;
}
else if (millis() - Time > 1000)
break;
if (check_super(T1, E1, wall1) == 2)
{ return; }
}
else
while (1)
{
if (check_super(T1, E1, wall1) == 1)
{
Time = millis() - Time;
break;
}
else if (millis() - Time > 1000)
break;
else if (check_super(T2, E2, wall2) == 2)
{ return; }
}
if (Time < 300)
{
BUZZER(2000);
digitalWrite(LED, LOW);
}
delay(1000);
}

int check_super(int tri, int echo, float wall)


{
delay(10);
float F = get_dis(tri, echo);
Serial.println(F);
int B = ((wall * (float)4) / (float)5 > F) ? 1 : 0;
B = (F > (float)1000) ? 2 : B;
delay(10);
return B;
}
float get_dis(int tri, int echo)
{
digitalWrite(tri, HIGH);
delayMicroseconds(15);
digitalWrite(tri, LOW);
delayMicroseconds(10);
float dis = 0.017 * pulseIn(echo, HIGH);
return dis;
}

void BUZZER(int T)
{
long Time = T + millis();
int delayed_T = 0, LED_state = HIGH;
while(1)
{
digitalWrite(BUZZ, HIGH);
delay(1);
digitalWrite(BUZZ, LOW);
delay(1);
if (millis() > Time)
break;
delayed_T += 2;
if (delayed_T > 100)
{
digitalWrite(LED, LED_state);
LED_state = (LED_state == HIGH) ? LOW : HIGH;
delayed_T = 0;
}
}
}

178) Arduino Servo Control Panel


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Breadboard (generic)

× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1

SparkFun Pushbutton switch 12mm

× 3

Resistor 10k ohm

× 3

Rotary potentiometer (generic)

× 2

Resistor 221 ohm

× 1

Capacitor 100 µF

× 2

Servos (Tower Pro MG996R)


× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


The idea is to realize an instrument panel to control a servo and display the
angle and sweep mode on a LCD screen. Although compact and cheap
boards dedicated to servo testing do exist, I wanted to realize a device to
control and display the flap deflection of a wing model in a little, didactic
wind tunnel and I wanted to do it, as far as possible, with the items
provided with the Arduino Starter Kit.
How it works
Usually, servo testers give the possibility to control the servo angle by
rotating a knob, put the servo in the neutral position, and sweep
automatically between the minimum and maximum angle positions. Since
my objective is to provide a user interface for wing angle of attack
variation or control surface deflection, I do not need to put the servo in the
neutral position (i.e. 90° if the servo rotates between 0° and 180°), but I
need a switch to set a reference zero angle. In fact, the servo may be at any
position while the wing (or control surface) angle relative to the wind is
null. Also, I am interested to measure the deflection of the control surface
relative to the reference zero. Finally, I want the servo to automatically
sweep between two given angles around the reference zero at a certain
angular velocity, which I want to control, although I am not interested in
measuring it (I just want it to rotate faster or slower).
In my case, I used a little servo with JR connector, I assumed that the flap
angle is equal to the servo angle (this is a rough estimate), and the auto-
sweep function has been set between -30° and +60° (positive values,
means increase in lift force: flap rotates down, the aerodynamic force
increases upwards.
The panel operates in two modes: manual control and auto sweep. The
user interface provides three buttons, a knob, and a LCD screen. The
display shows the servo angle in manual control mode and the limit angles
(set in the Arduino code and not editable from the panel) in auto-sweep
mode. The switch buttons serve as zeroing the reference angle, commuting
between the manual control and auto-sweep mode, and changing the sign
of the angle reported on the LCD display. In fact, since the servo rotation
may be opposite to the desired convention, the last switch button gives the
possibility to change the sign on the screen, but does not invert the rotation
of the servo, which is linked to the rotation of the knob. In manual control
mode, the servo knob controls the servo angle, which is shown on the
LCD screen. Initially, the display shows the servo absolute angle, after the
zeroing it shows the servo angle relative to that zero. In the auto-sweep
mode, the servo knob controls the rotation rate by adjusting the delay
between consecutive rotations (between 15 and 100 ms).
Final note
I have managed to use items from the Arduino Starter Kit, except for the
bigger breadboard. The panel shown in the final picture has a slightly
different arrangement from the breadboard scheme for assembly reasons.
Consider that you may need an external power source to control the servo,
according to the voltage and power consumption of your device. If the
servo vibrates, check your connections, then try to add an external power
source. You may need to rearrange some of the items on your breadboard.
Although incorrect, I have kept the original names for the code filename,
variables, and display statements. Angle of attack, alpha, AOA are
synonymous, defined as the angle between a reference line and the wind
direction in the longitudinal plane. In my application, I have changed the
deflection angle of a control surface, which also changes the angle of
attack, by altering the local wind direction due to the pressure difference
between the upper and lower wing surfaces. By AOA on the display I
mean servo angular position, which is related to the control surface
deflection by the linkage system. The variation of angle of attack and lift
force due the control surface deflection is related to the control surface
effectiveness.
The portable wind tunnel. This tutorial shows how to control the pitch of
the model inside.

A wing installation in the wind tunnel. This tutorial is about the control
panel not shown in this picture, but the description of the apparatus
explains the motivations of the control panel functionality.
My arrangement of the Servo Control Panel.

SCHEMATICS
CODE

#include <LiquidCrystal.h>
#include <Servo.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Servo myServo;

int const signPin = 6; // button to switch sign of the angle


int const sweepPin = 7; // button to turn auto angle sweep on/off
int const zeroPin = 8; // button to set reference
int const pot = A0; // potentiometer that controls angle/rate
int potVal; // value of the angle/rate
int angle; // angle of the servo
int rotDelay; // speed of the servo (delay between angles)
int zero = 0; // reference angle of attack
int signSwitch = 1; // sign of the angle (positive or negative)
int alpha; // angle of attack
int sweepState = 0; // auto sweep state (on/off)
int lowLimit = -30; // low angle limit for auto sweep
int highLimit = 60; // high angle limit for auto sweep
int newLowLimit; // low limit angle from the zero
int newHighLimit; // high limit angle from the zero

void setup() {
pinMode(zeroPin, INPUT);
pinMode(signPin, INPUT);

lcd.begin(16, 2);
lcd.print("Angle of attack");
lcd.setCursor(0, 1);
lcd.print("control panel");
delay(3000);
lcd.clear();

myServo.attach(9); // servo is attached to pin 9


Serial.begin(9600);
}

void loop() {

// if the zero button is pressed the angle of attack is set to 0


if (digitalRead(zeroPin) == HIGH) {
zero = angle;
// centers the auto sweep limits around the new zero
newLowLimit = lowLimit + zero;
newHighLimit = highLimit + zero;
Serial.print("Setting low angle limit: ");
Serial.println(newLowLimit);
Serial.print("Setting high angle limit: ");
Serial.println(newHighLimit);
delay(100);
}

// if the sign button is pressed changes the sign of the angle


if (digitalRead(signPin) == HIGH) {
signSwitch = -1 * signSwitch;
delay(100);
}

alpha = signSwitch * (angle - zero); // angle of attack respect to reference

// check if auto sweep button has been pressed


if (digitalRead(sweepPin) == HIGH) {
sweepState = 1;
Serial.print("Auto sweep state = ");
Serial.println(sweepState);
lcd.clear();
delay(100);
}

// turn on auto sweep if auto sweep button has been pressed


if (sweepState == 1) {

// check if alpha range is out of servo range


if (newLowLimit < 0 || newLowLimit > 179) {
newLowLimit = 0;
Serial.print("Actual low angle limit: ");
Serial.println(newLowLimit);
}
if (newHighLimit > 179 || newHighLimit < 0) {
newHighLimit = 179;
Serial.print("Actual high angle limit: ");
Serial.println(newHighLimit);
}

// if auto sweep button has been released


if (digitalRead(sweepPin) == LOW) {

lcd.home();
lcd.print(lowLimit);
lcd.print(" < AOA < ");
lcd.print(highLimit);
lcd.setCursor(0, 1);
lcd.print("Auto sweep ON");

// check the angle sign to assign correct sweep angles sequence


if (signSwitch == 1) {
angle = zero + alpha;
}
else {
angle = zero - alpha;
newHighLimit = -lowLimit + zero;
newLowLimit = -highLimit + zero;
}

while (angle < newHighLimit) {


// assign delay between angles, varying servo rotational speed
potVal = analogRead(pot);
Serial.print("potVal: ");
Serial.print(potVal);
rotDelay = map(potVal, 0, 1023, 15, 100);
Serial.print(", rotDelay: ");
Serial.print(rotDelay);
Serial.println(" ms");
myServo.write(angle);
delay(rotDelay);

// if during loop auto sweep button is pressed exit the loop


if (digitalRead(sweepPin) == HIGH) {
sweepState = 0;
Serial.print("Auto sweep state = ");
Serial.println(sweepState);
lcd.clear();
delay(100);
goto manual;
}
angle++;
}

while (angle > newLowLimit) {


// assign delay between angles, varying servo rotational speed
potVal = analogRead(pot);
Serial.print("potVal: ");
Serial.print(potVal);
rotDelay = map(potVal, 0, 1023, 15, 100);
Serial.print(", rotDelay: ");
Serial.print(rotDelay);
Serial.println(" ms");
myServo.write(angle);
delay(rotDelay);

// if during loop auto sweep button is pressed exit the loop


if (digitalRead(sweepPin) == HIGH) {
sweepState = 0;
Serial.print("Auto sweep state = ");
Serial.println(sweepState);
lcd.clear();
delay(100);
goto manual;
}
angle--;
}

}
}
else { // if auto sweep is turned off
manual: // label destination of interrupted loop
lcd.setCursor(0, 1);
lcd.print("Manual control");

potVal = analogRead(pot);
Serial.print("potVal: ");
Serial.print(potVal);
angle = map(potVal, 0, 1023, 0, 179);
Serial.print(", angle: ");
Serial.print(angle);
myServo.write(angle);
delay(15);
Serial.print(", zero: ");
Serial.print(zero);
Serial.print(", AOA: ");
Serial.println(alpha);

lcd.home();
lcd.print("AOA = ");
// To avoid overlapping text among readings I must use blank
// characters (space) when needed over the four predicted positions.

// between -179 and -100 four digits are assigned


if (alpha >= -179 && alpha <= -100) {
lcd.print(alpha);
lcd.print(" deg"); // no space after
}
// between -99 and -10 three digits are assigned
else if (alpha >= -99 && alpha <= -10) {
lcd.print(alpha);
lcd.print(" deg "); // one space after
}
// between -9 and -1 two digits are assigned
else if (alpha >= -9 && alpha <= -1) {
lcd.print(alpha);
lcd.print(" deg "); // two spaces after
}
// between 0 and 9 only one digit is assigned
else if (alpha >= 0 && alpha <= 9) {
lcd.print(alpha);
lcd.print(" deg "); // three spaces after
}
// between 10 and 99 two digits are assigned
else if (alpha >= 10 && alpha <= 99) {
lcd.print(alpha);
lcd.print(" deg "); // two spaces after
}
// between 100 and 179 three digits are assigned
else if (alpha >= 100 && alpha <= 179) {
lcd.print(alpha);
lcd.print(" deg "); // one spaces after
}
// out of -179,+179 the servo cannot rotate
else {
lcd.home();
lcd.print("Error: signal");
lcd.setCursor(0,1);
lcd.print("out of range.");
delay(1000);
lcd.clear();
}
}
}
179) Arduino Sensing the Comfort Level of Atmosphere Using
Humidex

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Resistor 100 ohm


× 1

LED (generic)
5 LED of different colors. I used
× 5
white, blue, green, yellow and red.

DHT22 Temperature Sensor

× 1

Jumper wires (generic)

× 15
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


The human comfort level not only determined by temperature but also
with humidity. For example, at 20 °C and 80 % relative humidity is
much more suffocating than 20 °C and 25 % relative humidity.
The humidex (short for humidity index) is an index number used to
describe how hot the weather feels to the average person, by combining
the effect of heat and humidity. The ranges are as follows:
20 to 29: Little to no discomfort
30 to 39: Some discomfort
40 to 45: Great discomfort; avoid exertion
Above 45: Dangerous; heat stroke quite possible
But the calculation of the humidex is a little complicated. The formula
is as follows:

Formula for HUMIDDEX


Where,
Tair is the air temperature in °C
Tdew is the dew point in °C
Briefly, we can define dew point as follows: "The atmospheric
temperature below which water droplets begin to condense and dew
can form".
But our DHT22 temperature and humidity sensor can sense the
atmospheric temperature and humidity, not the dew point which is
needed to execute the formula of humidex.
Thus, another formula was used for calculation of dew point from
temperature and humidity:

Formula for Dew Point from air temperature and humidity


In the code, first the temperature and humidity value was captured from
the sensor, further dew point is calculated and finally the value of
humidex has been determined.
Afterwards, the LEDs' are blinked according to the calculated values of
humidex for the users' easiness. Here are the outputs:
Green LED blinks (5 sec): No discomfort (Humidex is less than 20).
White LED blinks (5 sec): Little discomfort (Humidex is between 20 to
29).
Yellow LED blinks (5 sec): Some extent discomfort (Humidex is
between 30 to 39)
Blue LED blinks (5 sec): High extent discomfort (Humidex is between
40 to 45)
Red LED blinks (5 sec): Very dangerous; sun stroke may possible
(Humidex is higher than 45)
Green, White, Yellow LEDs' blinks for 1 sec sequentially: Sensor is not
working.
This in a nutshell, this project is developped using DHT22 Sensor and
arduino aiming to sense the discomfort/comfort level by blinking LED.
SCHEMATICS

CODE

//* Representing the comfort level by blinking of LED using HUMIDEX by DHT22 sensor
and arduino Uno.

//Libraries
#include <DHT.h>;
#include <math.h>

//Constants
#define DHTPIN 7 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)

DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino

//Variables
double hum; //Stores humidity value
double temp; //Stores temperature value
double B; // Stores the value of intermediate parameter.
double dew; // Stores the value of Dew temperature
long humidex; // Stores the value of HUMIDEX
const int LED1 = 02; // White LED connected to digital pin 2
const int LED2 = 04; // Blue LED connected to digital pin 4
const int LED3 = 06; // Green LED connected to digital pin 6
const int LED4 = 10; // Yellow LED connected to digital pin 8
const int LED5 = 12; // Red LED connected to digital pin 10

void setup()
{

dht.begin();
pinMode(LED1, OUTPUT); // sets the digital pin as output
pinMode(LED2, OUTPUT); // sets the digital pin as output
pinMode(LED3, OUTPUT); // sets the digital pin as output
pinMode(LED4, OUTPUT); // sets the digital pin as output
pinMode(LED5, OUTPUT); // sets the digital pin as output
}

void loop()
{
delay(2000);
//Read data and store it to variables hum and temp
hum = dht.readHumidity();
temp= dht.readTemperature();
B=(log(hum/100)+((17.27*temp)/(237.3+temp)))/17.27; // value of "B", the intermediate
dimentionless parameter has been calculated.
dew=(237.3*B)/(1-B); // The value of dew point has been calculated
humidex=temp+0.5555*(6.11*exp(5417.753*(1/273.16-1/(273.15+dew)))-10); // the value
of HUMIDEX has been claculated.

if (humidex<0){ // the situation when sensor is not working ! i.e NaN is coming out of the
humidity and temperature value.
digitalWrite(LED1, HIGH); // turns the Green LED (numbered as 1) on
delay(1000); // wait for 1 sec
digitalWrite(LED1, LOW); // turns the Green LED (numbered as 1) off
digitalWrite(LED2, HIGH); // turns the white LED (numbered as 1) on
delay(1000); // wait for 1 sec
digitalWrite(LED2, LOW); // turns the White LED (numbered as 1) off
digitalWrite(LED3, HIGH); // turns the yellow LED (numbered as 1) on
delay(1000); // wait for 1 sec
digitalWrite(LED3, LOW); // turns the yellow LED (numbered as 1) off
}
else if (humidex>=0 && humidex <20){
digitalWrite(LED1, HIGH); // turns the green LED (numbered as 1) on
delay(5000); // wait for 5 sec
digitalWrite(LED1, LOW); // turns the green LED (numbered as 1) off
}
else if (humidex>=20 && humidex <30){
digitalWrite(LED2, HIGH); // turns the White LED (numbered as 2) on
delay(5000); // wait for 5 sec
digitalWrite(LED2, LOW); // turns the white LED (numbered as 2) off
}
else if (humidex>=30 && humidex <40){
digitalWrite(LED3, HIGH); // turns the Yellow LED (numbered as 3) on
delay(5000); // wait for 5 sec
digitalWrite(LED3, LOW); // turns the Yellow LED (numbered as 3) off
}
else if (humidex>=40 && humidex <45){
digitalWrite(LED4, HIGH); // turns the blue LED (numbered as 4) on
delay(5000); // wait for 5 sec
digitalWrite(LED4, LOW); // turns the blue LED (numbered as 4) off
}

else {
digitalWrite(LED5, HIGH); // turns the red LED (numbered as 5) on
delay(5000); // wait for 5 sec
digitalWrite(LED5, LOW); // turns the red LED (numbered as 5) off
}
}

180) Arduino Noas Protect


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

PIR Motion Sensor (generic)

× 1

Alphanumeric LCD, 16 x 2
× 1

Relay (generic)
× 1

LED (generic)

× 1
APPS AND ONLINE SERVICES
Jupyter Notebook

ABOUT THIS PROJECT


My project is designed to detect intruders in private areas, like homes
and office spaces. I decided to make it because its a business idea I
have and pre-installed alarm systems are too expensive and have not
much room for improvement, this way I'll challenge the market. My
intention is to go as far as synchronizing it to a smart home.
How it works; With the keypad and LCD screen, the user will be able
to activate the alarm when ever they choose to and set their own
password after overriding the temporal pass key. After activation, the
PIR motion sensor will be monitoring and if any intrusion a signal will
be sent to the output buzzer, where with an optocoupler transistor and a
relay I have connected a 24V sounder. And to reset, the alarm a
password has to be keyed in through the keypad.
SCHEMATICS
CODE

//#include <Key.h>
#include <Keypad.h>
#include <LiquidCrystal.h>

#define Bz 11
#define rLed 10
#define gLed 9

int pirPin = 13;


int sensorValue = LOW; //note sure what this is just yet //default sensor state

long i;
int screenOffMsg =0;
String password="1234";
String temPassword;
boolean activated = false; //checks the state of the alarm
boolean isActivated;
boolean activateAlarm = false; // check where this is being used
boolean alarmActivated = false;
boolean enteredPassword; // checks the stated of the password
boolean passChangeMode = false;
boolean passChanged =false;
//keypad
const byte Rows = 4;
const byte Cols = 4;
char keypressed;
char KeyMap [Rows][Cols] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};

byte ROWPINS[Rows] = {1, 2, 3, 4};


byte COLPINS[Cols] = {5, 6, 7, 8};

Keypad myKeypad = Keypad( makeKeymap(KeyMap),ROWPINS, COLPINS, Rows,


Cols);
//LCD
const int rs = A0, en = A1, d4 = A2, d5 = A3, d6 = A4, d7 = A5;
LiquidCrystal lcd( rs, en, d4, d5, d6, d7);

void setup () {
lcd.begin(16,2);
pinMode(Bz, OUTPUT);
pinMode(pirPin, INPUT);
}
void loop() {

if (activateAlarm){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Alarm will be");
lcd.setCursor(0,1);
lcd.print("activated in");
int countdown = 9;
while (countdown != 0) {
lcd.setCursor(13,1);
lcd.print(countdown);
countdown --;
tone(Bz, 700, 100);
delay(1000);
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Alarm Activated!");

//sensorValue = digitalRead(pirPin);

digitalWrite(rLed, HIGH);
digitalWrite(gLed, LOW);
activateAlarm = false;
alarmActivated= true;
}
//trigger
if (alarmActivated == true){
sensorValue = digitalRead(pirPin);

if(sensorValue == HIGH) {
lcd.clear();
enterPassword();

}
else {
noTone(Bz);
digitalWrite(rLed, HIGH);
}

}
if (!alarmActivated) {
if(screenOffMsg == 0){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("A - Activate");
lcd.setCursor(0,1);
lcd.print("B - Change Pass");
screenOffMsg = 1;
digitalWrite(rLed, LOW);
digitalWrite(gLed, HIGH);
}
keypressed = myKeypad.getKey();
if (keypressed == 'A'){
tone(Bz, 1000, 200);
activateAlarm = true;

else if (keypressed =='B') {


lcd.clear();
int i =1;
tone(Bz, 2000, 100);
temPassword = "";
lcd.setCursor(0,0);
lcd.print("Current Password");
lcd.setCursor(0,1);
lcd.print(">");
passChangeMode = true;
passChanged = true;
while(passChanged) {
keypressed = myKeypad.getKey();
if (keypressed != NO_KEY){
if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
keypressed == '8' || keypressed == '9' ) {
temPassword += keypressed;
lcd.setCursor(i,1);
lcd.print("*");
i++;
tone(Bz, 2000, 100);
}
}
if (i > 5 || keypressed == '#') {
temPassword = "";
i=1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Current Password");
lcd.setCursor(0,1);
lcd.print(">");
}
if ( keypressed == '*') {
i=1;
tone(Bz, 2000, 100);
if (password == temPassword) {
temPassword="";
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set New Password");
lcd.setCursor(0,1);
lcd.print(">");
while(passChangeMode) {
keypressed = myKeypad.getKey();
if (keypressed != NO_KEY){
if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
keypressed == '8' || keypressed == '9' ) {
temPassword += keypressed;
lcd.setCursor(i,1);
lcd.print("*");
i++;
tone(Bz, 2000, 100);
}
}
if (i > 5 || keypressed == '#') {
temPassword = "";
i=1;
tone(Bz, 2000, 100);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set New Password");
lcd.setCursor(0,1);
lcd.print(">");
}
if ( keypressed == '*') {
i=1;
tone(Bz, 2000, 100);
password = temPassword;
passChangeMode = false;
passChanged = false;
screenOffMsg = 0;
}
}
}
}
}
}
}
}
void enterPassword() {
// tone(Bz, 700, 100);
// delay (1000);
// tone(Bz, 700, 100);
//delay(10000);
// tone(Bz, 700, 100);
int k=5;
temPassword = "";
activated = true;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" *** ALARM *** ");
lcd.setCursor(0,1);
lcd.print("Pass>");
while(activated) {
keypressed = myKeypad.getKey();
if (keypressed != NO_KEY){
if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
keypressed == '8' || keypressed == '9' ) {
temPassword += keypressed;
lcd.setCursor(k,1);
lcd.print("*");
k++;
}
}
if (k > 9 || keypressed == '#') {
temPassword = "";
k=5;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" *** ALARM *** ");
lcd.setCursor(0,1);
lcd.print("Pass>");
}
if ( keypressed == '*') {
if ( temPassword == password ) {
activated = false;
alarmActivated = false;
noTone(Bz);
screenOffMsg = 0;
}
else if (temPassword != password) {
lcd.setCursor(0,1);
lcd.print("Wrong! Try Again");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" *** ALARM *** ");
lcd.setCursor(0,1);
lcd.print("Pass>");
}
}
//
tone(Bz, 1000);
}
noTone(Bz);
digitalWrite(rLed, HIGH);

}
181) Arduino Office Status Marquee

COMPONENTS AND SUPPLIES

Arduino Nano R3

× 1

SainSmart MAX7219 Dot Matrix


Module 4 in one for Arduino × 2
NulSom Inc. Ultra Compact RS232
to TTL Converter with Male DB9
(3.3V to 5V) × 1

ABOUT THIS PROJECT


For years I've had many people come to see me in my office and
struggle with understanding that I'm on a video call with someone from
my computer. So when I started working on Arduino for my chicken
coop - more to come later - I came across the 8x8 LED matrix and the
ability to gang them together. No I have a 64x8 scrolling marquee that
allows me to announce to my visitors that I'm on a call, or out to lunch,
or anything else that I have pre-programmed into my RS232 interface
to control the marquee. Depending on the length of the message it may
even scroll!
I used the examples from the MD_MAX72XX library to help me piece
these together.
SCHEMATICS
CODE

// my office marquee - currently connected via Contact Closure and RS232 to a Crestron
MP3E for message control.
//
// Use the MD_MAX72XX library to scroll text on the display
//
// Demonstrates the use of the callback function to control what
// is scrolled on the display text.
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Speed for the display is controlled by a pot on SPEED_IN analog in.

#include <MD_MAX72xx.h>
#include <SPI.h>
#define PRINT_CALLBACK 0

#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }

// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 8

#define CLK_PIN 13 // Digital or SCK - // originally pin 13


#define DATA_PIN 11 // PWM or MOSI - // originally pin 11
#define CS_PIN 10 // PWM or SS - // originally pin 10

// SPI hardware interface


MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

// Scrolling parameters
#define SCROLL_DELAY 75 // in milliseconds

#define CHAR_SPACING 1 // pixels between characters

// Global message buffers shared by Serial and Scrolling functions


#define BUF_SIZE 75
char curMessage[BUF_SIZE];
char newMessage[BUF_SIZE];
bool newMessageAvailable = false;

uint16_t scrollDelay; // in milliseconds

// scrolling/static switch status


const int scrollSwitch = 2;
int scrollYes = 0;

void readSerial(void)
{
static uint8_t putIndex = 0;

while (Serial.available())
{
newMessage[putIndex] = (char)Serial.read();
//Serial.println(newMessage);
if ((newMessage[putIndex] == '\n') || (putIndex >= 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

9V battery (generic)

× 1

AA Batteries
× 1

Led matrix 8x8 common cathode


I did use the GMM-23088CSB,
but every generic matrix should × 1
work, just need to ensure what's
the pinout diagram.
Breadboard (generic)

× 1

Resistor 330 ohm

× 8

9V Battery Clip

× 1

General Purpose Transistor NPN

× 1

Switch
× 1

Hand lamp
You can use any source of light
× 1
that produces a directed beam of
light. I did use a led hand lamp:
NF-A651.
Resistor 2.7K ohm
× 1

Jumper wires (generic)


Any wire should work
× 1

Cardboard box
× 1
Recycled carton ??
Glue
× 1

Matt black paper


× 1
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<19; j++){
pinMode(j, OUTPUT);
}
digitalWrite(18, LOW);
}

void SetChar(char p)
{
Clear();
for (int fil = 0; fil <8 ; fil++)
{
delayMicroseconds(350);
digitalWrite( fil + 10 , LOW) ; // Activamos la fila para el barrido
//byte F = N[fil] ;
byte F = Selecciona( p, fil);
for (int col =7; col >= 0 ; col--)
{
delayMicroseconds(350);
digitalWrite(8-col, LOW); //Bajamos la columna
bool b = GetBit(F, col) ;
if (b){
digitalWrite( 9 - col ,HIGH); //Levantamos la columna, con su pin
}
else {
digitalWrite( 9 - col ,LOW); // Si 0, apagamos
}
} // Solo si b es 1
digitalWrite( fil + 10 , HIGH) ; // Apagamos fila antes de salir
}
}

bool GetBit( byte N, int pos)


{ // pos = 7 6 5 4 3 2 1 0
int b = N >> pos ; // Shift bits
b=b&1; // coger solo el ultimo bit
return b ;
}

void Clear()
{
for (int j=2; j<10; j++) // Valores de los pines de columna
digitalWrite(j, LOW); // Todos apagados
for (int k= 10 ; k<18 ; k++){
digitalWrite(k, HIGH); // Todas las filas cortadas
}
}

String s;
long t;
char c;
void loop()
{
s = "loadin n n n n";
for ( int n = 0; n < 14; n++ )
{
t = millis();
c = s[n];
if(n < 6){
while ( millis()< t + 1000)
SetChar(c);
} else {
while ( millis()< t + 380)
SetChar(c);
}
}
delay(500);

//Jenny
s = "4";
t = millis();
c = s[0];
while(millis() < t + 4000){
SetChar(c);
}

//Corazn
s = "5";
t = 0;
t = millis();
c = s[0];
while(millis() < t + 4000){
SetChar(c);
}

//Flecha a la derecha parpadeando


for(int i = 0; i < 6; i++){
s = "6 ";
for(int n = 0; n < 2; n++){
t = millis();
c = s[n];
while(millis() < t + 600){
SetChar(c);
}
}
}

//Enciende el foco con el transistor y el relay


digitalWrite(18, HIGH);

//Corazn eterno
s = "5";
c = s[0];
while(1){
SetChar(c);
}
}
183) Arduino Control Music Volume and Ledbar using Slider of
1Sheeld
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

1Sheeld

× 1

USB-A to Mini-USB Cable


× 1

SparkFun led bar


× 1

Jumper wires (generic)

× 1

9V battery (generic)

× 1

Android device

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


The project is about how to control the music volume and visualize the
volume level on a led bar in an easy way by using the amazing
1Sheeld.
1Sheeld turns your smart phone into more than 40 different Arduino
shields so it's saves a lot of money and gives you the ability to make
great projects and it's available at both android studio and apple store.
You can check all 1Sheeld's tutorials which will take you from the
early beginning into more and more advanced projects from that
link. http://1sheeld.com/tutorials/
And you can order it from here
All the details of how it works will be in the video uploaded and you
can find the hardware connections in the schematic.
SCHEMATICS
CODE

#define CUSTOM_SETTINGS
#define INCLUDE_SLIDER_SHIELD
#define INCLUDE_MUSIC_PLAYER_SHIELD
/* Include 1Sheeld library. */

#include <OneSheeld.h>

byte value; /* define a variable to hold the slider values. */

int led1 = 2; /* connecting first led to pin 2. */


int led2 = 3; /* connecting second led to pin 3. */
int led3 = 4; /* connecting third led to pin 4. */
int led4 = 5; /* connecting forth led to pin 5. */
int led5 = 6; /* connecting fifth led to pin 6. */
int led6 = 7; /* connecting sixth led to pin 7. */
int led7 = 8; /* connecting seventh led to pin 8. */
int led8 = 9; /* connecting eights led to pin 9. */
int led9 = 10; /* connecting ninth led to pin 10. */
int led10 = 11; /* connecting tenth led to pin 11. */

void setup() {
/* Set the LEDs pins as output. */

pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(led4,OUTPUT);
pinMode(led5,OUTPUT);
pinMode(led6,OUTPUT);
pinMode(led7,OUTPUT);
pinMode(led8,OUTPUT);
pinMode(led9,OUTPUT);
pinMode(led10,OUTPUT);

/* Start communication. */
OneSheeld.begin();
}

void loop() {
value = Slider.getValue(); /* get the slider value and keep it in the "value" variable. */
value = map(value,0,255,0,10); /* mapping the analog values of slider into values between
0 and 10 -*/
/*so the music volume will understand it. */

switch (value) /*switch between the values to determine whicch leds to turn on and which
to turn off.*/

{
case 1:
digitalWrite(led1,HIGH);
digitalWrite(led2,LOW);
digitalWrite(led3,LOW);
digitalWrite(led4,LOW);
digitalWrite(led5,LOW);
digitalWrite(led6,LOW);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 2:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,LOW);
digitalWrite(led4,LOW);
digitalWrite(led5,LOW);
digitalWrite(led6,LOW);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 3:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,LOW);
digitalWrite(led5,LOW);
digitalWrite(led6,LOW);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 4:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,HIGH);
digitalWrite(led5,LOW);
digitalWrite(led6,LOW);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 5:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,HIGH);
digitalWrite(led5,HIGH);
digitalWrite(led6,LOW);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 6:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,HIGH);
digitalWrite(led5,HIGH);
digitalWrite(led6,HIGH);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 7:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,HIGH);
digitalWrite(led5,HIGH);
digitalWrite(led6,HIGH);
digitalWrite(led7,HIGH);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 8:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,HIGH);
digitalWrite(led5,HIGH);
digitalWrite(led6,HIGH);
digitalWrite(led7,HIGH);
digitalWrite(led8,HIGH);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

break;

case 9:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,HIGH);
digitalWrite(led5,HIGH);
digitalWrite(led6,HIGH);
digitalWrite(led7,HIGH);
digitalWrite(led8,HIGH);
digitalWrite(led9,HIGH);
digitalWrite(led10,LOW);

break;

case 10:
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
digitalWrite(led4,HIGH);
digitalWrite(led5,HIGH);
digitalWrite(led6,HIGH);
digitalWrite(led7,HIGH);
digitalWrite(led8,HIGH);
digitalWrite(led9,HIGH);
digitalWrite(led10,HIGH);

break;
default:
digitalWrite(led1,LOW);
digitalWrite(led2,LOW);
digitalWrite(led3,LOW);
digitalWrite(led4,LOW);
digitalWrite(led5,LOW);
digitalWrite(led6,LOW);
digitalWrite(led7,LOW);
digitalWrite(led8,LOW);
digitalWrite(led9,LOW);
digitalWrite(led10,LOW);

MusicPlayer.setVolume(value); /*send the value of slider to the music volume.*/


MusicPlayer.play(); /* Turn on the music. */

}
184) Arduino Talking Tom

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

ISD1820 Module
× 1

Jumper wires (generic)

ABOUT THIS PROJECT


Actually, my project works with an Arduino Uno and a sound/voice
module. The wiring is displayed in the schematic below.
It then continues to a 0.5 Ohm speaker which can be connected to the
sound/voice module directly, or it can be connected to an amplifier and a
speaker. The outlook was roughly made with boxes. When you use the
amplifier, then the snoring noise is also amplified. For that use, you'll need
some combinations of capacitors and resistors in the input to control them.
I used a 4440 stereo amplifier and a 4W, 4 Ohm speaker.
Very important
The module can record only up to 10 seconds in this connection type. The
code for Arduino is as follows below:
int Rec = 11;
int Play = 13;
void setup()
{
pinMode(Rec, OUTPUT);
pinMode(Play, OUTPUT);
}
void loop()
{
digitalWrite(Rec, HIGH);
delay(10000);
digitalWrite(Rec, LOW);
delay(50);
digitalWrite(Play, HIGH);
delay(50);
digitalWrite(Play, LOW);
delay(10000);
}

SCHEMATICS
CODE

int Rec = 11;


int Play = 13;

void setup()
{
pinMode(Rec, OUTPUT);
pinMode(Play, OUTPUT);
}

void loop()
{
digitalWrite(Rec, HIGH);
delay(10000);
digitalWrite(Rec, LOW);
delay(5000);
digitalWrite(Play, HIGH);
delay(100);
digitalWrite(Play, LOW);
delay(10000);
}
185) Arduino Sand Art Display

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO


see the construction manual PDF × 1
for all components.

5 V stepper motor 28BYJ-48 with


driver board ULN2003. × 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
see the construction manual PDF for all tools
needed.
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Imagine a Japanese zen garden built into a glass-covered picture frame.
Below the frame are electronics and robotics, creating geometric patterns
and images in the sand. The effect is enchanting and magical, it is really
zen-like to see ever-changing patterns and images slowly appear in the
sand.
The Sand Art Display is a modern version of this traditional zen sand
garden. It is a drawing machine that creates mandala-like patterns in the
sand. The operation of this display is as follows: under the glass top is a
thin layer of sand, under thes and a twin-engine robot moves a strong
magnet to steer a steel ball through the sand. The robot is controlled by an
Arduino mini computer playing a pattern program, similar to the way a
music player plays MP3 songs. The table calibrates itself when plugged in
and after this calibration a number of pre-programmed patterns can be
selected using the push buttons.
SCHEMATICS
CODE

/*
Stepper Motor Control progam for an X-Y table named "Sand Art Display".
This program drives two unipolar 5V DC stepper motors type 28BYJ-48.
The motors are attached to digital pins 4,5,6,7 and 8,9,10 and 11 of the Arduino UNO,
via a driver board with IC ULN2003.
The motor power supply on this board is a separate 5V DC supply.
GND is connected to the GND of the Arduino.
The motors drive both axis of the sand art table with a 250 mm rack gear.
It starts the movement blue, yellow or white when the motors are resting in the full left &
up position.
See www.apinventions.wordpress.com for the Sand Art Display building instructions.
*/

#include <Stepper.h>
//this sequence is special for the 28BYJ-48 stepper motor.
Stepper myStepperX(1024, 8,10,9,11);Stepper myStepperY(1024, 4,6,5,7);

int button = A1; // analog button value 736(white)/451(yellow)/14(blue)


int select = 0; // select which road to follow...
int resetled = A2; // green led ready for instructions
int whiteled = A3; // path 1
int yellowled = A4; // path 2
int blueled = A5; // path 3
int xstop = 12; // port end position left or right
int ystop = 3; // port end position up or down
int speed1 = 10; // slow speed
int speed2 = 15; // medium speed
int speed3 = 25; // fast speed
int up = 50; // length of standard step up
int down = -50;// length of standard step down
int left = 50; // length of standard step left
int right = -50;// length of standard step right
int n=0; // counter flag up/down
int m=0; // counter flag left/right
int x=0; // left/right number of steps
int y=0; // up/down number of steps
int d=0; // counter for step difference

void setup() {
myStepperX.setSpeed(speed3);myStepperY.setSpeed(speed3);
pinMode(3,INPUT_PULLUP);pinMode(12,INPUT_PULLUP);pinMode(A1,INPUT_PULLUP
pinMode(A2,OUTPUT);pinMode(A3,OUTPUT);pinMode(A4,OUTPUT);pinMode(A5,OUTPUT
myStepperX.step(5*left);myStepperY.step(5*up);// always move to left/up corner start
position
}

void loop() {
myStepperX.setSpeed(speed3);myStepperY.setSpeed(speed3);
digitalWrite(whiteled,LOW);digitalWrite(yellowled,LOW);digitalWrite(blueled,LOW);
y = digitalRead(ystop);if(y==HIGH) {myStepperY.step(4*up);}
x= digitalRead(xstop);if(x==HIGH) {myStepperX.step(4*left);}

if (y==LOW && x==LOW) // left/up start position


{ digitalWrite(resetled,HIGH);
select = analogRead(button);
if (select <50){blue();}
if (select >50 && select <600){yellow();}
if (select >600 && select <800){white();}
}

}
//PONG
void blue(){
myStepperX.setSpeed(speed2);myStepperY.setSpeed(speed2);
digitalWrite(blueled,HIGH);digitalWrite(resetled,LOW);

y = digitalRead(ystop);if(y==LOW && n==0){myStepperY.step(4*down);n=1;}


y = digitalRead(ystop);if(y==HIGH && n==1){myStepperY.step(2*down);}
y = digitalRead(ystop);if(y==LOW && n==1){myStepperY.step(4*up);n=0;}
y = digitalRead(ystop);if(y==HIGH && n==0){myStepperY.step(2*up);}

x = digitalRead(xstop);if(x==LOW && m==0){myStepperX.step(4*right);m=1;}


x = digitalRead(xstop);if(x==HIGH && m==1){myStepperX.step(2*right);}
x = digitalRead(xstop);if(x==LOW && m==1){myStepperX.step(4*left);m=0;}
x = digitalRead(xstop);if(x==HIGH && m==0){myStepperX.step(2*left);}
blue();
}

//PLOUGH
void yellow(){
myStepperX.setSpeed(speed2);myStepperY.setSpeed(speed2);
digitalWrite(yellowled,HIGH);digitalWrite(resetled,LOW);
x=73-d;myStepperX.step(x*right);
y=56-d;myStepperY.step(y*down);
d=d+3;
x=73-d;myStepperX.step(x*left);
y=56-d;myStepperY.step(y*up);
d=d+3;
while(y<5 || x< 5){} ;
yellow();
}

//WAFFLE
void white(){
myStepperX.setSpeed(speed2);myStepperY.setSpeed(speed2);
digitalWrite(whiteled,HIGH);digitalWrite(resetled,LOW);
if(d==0){
if(n==0){myStepperY.step(5*down);}
y = digitalRead(ystop);if(y==LOW && n==0){myStepperX.step(11*right);n=1;x=x+1;}
if(n==1){myStepperY.step(5*up);}
y = digitalRead(ystop);if(y==LOW && n==1){myStepperX.step(11*right);n=0;x=x+1;}
if(x >7){d=1;y=0;n=0;}
}
if (d==1){
if(n==0){myStepperX.step(5*left);}
x = digitalRead(xstop);if(x==LOW && n==0){myStepperY.step(11*down);n=1;y=y+1;}
if(n==1){myStepperX.step(5*right);}
x = digitalRead(xstop);if(x==LOW && n==1){myStepperY.step(11*down);n=0;y=y+1;}
while(y >5){};
}
white();
}

186) Arduino A Vay To Sort Out Your Resitors

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1
Alphanumeric LCD, 16 x 2

× 1

Resistor 100 ohm

× 1

Resistor 1k ohm

× 1

Resistor 10k ohm

× 1

Resistor 100k ohm

× 1

Resistor 1M ohm

× 1

Jumper wires (generic)


× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


The "demand" I address with this work is reading the value of a resistor
in a simple way to sort them back in the proper drawers and keep the
table uncluttered. Yes, there's the color codes but... ;-( YES, there's the
multimeter with the proper attachments but...
Is it not better to just plainly READ IT?

A 16x2 LCD just out of the kit provides the display needs in full
I started this first project as a way to learn better and make it available
a great idea to those who have just started with a basic kit.
So I started this first project as a way to learn better and make it
available a great idea (Federico's - see credits) to those who have just
started with a basic kit and the UNO board.
The theoretical principle that is applied here (and in many other
projects) is the "Voltage divider equation make difficult things simple it
is a way to calculate one resistor value that you don't know putting two
one after the other and reading how much of the total voltage the know
resistor make you read at its terminals. The nearer the two are the more
precise the result can be - so to make a balanced compromise we use
five different values of know sample resistors.
Let's get started!!!
You need to make ready the components. The scheme below will easily
take you to configure the breadboard. I used two different ones - to
keep the 16x2 LED display function as much similar as to those of the
tutorials (you should try the display as a separate part first, if you have
not done it yet!) and get more visibility on the simple resistor part
'addition'. There's plenty of space left on the main breadboard to move
it all on one - you just need to keep connected with the 5 green wires
and the yellow one as before.
Full -fritzing- breadboard view
When you have arranged the components in this way you can also try
to move it around checking with the schematics below:
Schematics
At the end it should be something like...
Now is time to open up the coding - pick up the code in the proper
section of this page and start reading it to feel it up. As everything in an
Open Source environment it is a collage of what others have built
before us. In particular all the sections that enable the visualization on
the LCD is very standard.
I added on the original project a FUNCTION - that is a separate piece
of code that gets AFTER the usual two sections of "setup" and "loop" -
that can be "called" to make a specific calculation or - in the case a
formatting - of one or more variables. I used it to transform a number
1.000.121, 34 in a string that is readable after the normal conventions
for resistors - such as 1MOhm. The rounding and formatting would
need a more extensive testing to check for all exceptions and
anomalies... help me there.
String OhmFormattingFunction(float Input) {
//FS 20200223 v0 - Ohm values formatting function **
String Result;
if (Input < 80) {
valore = (String(round(Input)));
suffisso = " ";
}
....
I confess I kept some words inside the code in the Italian (Leonardo's!)
language but it will take just a moment for you to replace them with...
whatever idiom you were born to or in the English we all share. There
are extensive debugging inserts in form of printed serial text to follow
the procedure from the monitor.
IMPROVEMENT PATH:
First of all you should make this yours by adapting it to your style
and needs - correct the unavoidable mistakes and try to improve the
calculations and/or the formatting letting us all know by commenting
(much appreciated)
I strongly suggest you buy a 0.96" OLED display and try it out - it is
quite inexpensive and easy to implement (see Federico's project)
Another way to get nearer to a finished "product" is to port it to a
Nano Every - I found that the pins are the same etc. (this requires
soldering and although it is not difficult, it implies a different level
of involvement).

SCHEMATICS
CODE
// lazyRmeter by FEDERICO VIVALDI all references to OLE display removed - pins
relocated
// lazyRmeter_v2_16x2 semplified by F.Stella 20200221 for UNO and serial print to be
ported to simple 16x2 display

// LCD 16x2 code - example added 9 Jul 2009 by Tom Igoe - modFS2020
//include the LCD library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin


// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//Resistenze di comparazione sul circuito:


//compR1 = 100 Ohm collegata a PIN 6 (lowest)
//compR2 = 1 kOhm collegata a PIN 7
//compR3 = 10 kOhm collegata a PIN 8
//compR4 = 100 kOhm collegata a PIN 9
//compR5 = 1 MOhm collegata a PIN 10 (top)

int R1 = 100;
int R2 = 1000;
int R3 = 10000;
long R4 = 100000;
long R5 = 1000000;
long Rn;

float Input;

String valore;
String suffisso;
float trans;

int compR1 = 6;
int compR2 = 7;
int compR3 = 8;
int compR4 = 9;
int compR5 = 10;

float raw = 0;
float Vout = 0;
float Ru = 0;
int analogOhm = A0;
void setup() {
Serial.begin(9600);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a fixed message title to the LCD.
lcd.print("Resistenza da: ");
}

void loop() {
//attivazione porte a cui sono collegate le resistenze campione
pinMode(compR1, OUTPUT); //parto attivando il pin 2 che va alla resistenza test pi alta
da 1M
pinMode(compR2, INPUT);
pinMode(compR3, INPUT);
pinMode(compR4, INPUT);
pinMode(compR5, INPUT);

digitalWrite(compR1, HIGH); //attiva la tensione a 5V sulla resistenza a 1 MOhm e


resistenza da misurare
raw = analogRead(analogOhm); //legge il valore su A0 della tensione su 1 Ohm

Rn = R5;

Serial.println(raw); //DEBUG
Serial.println("ref 1M"); //DEBUG

int rawLimitLow = 350; //originale 350


int rawLimitTop = 850; //originale 800

if (raw < rawLimitLow || raw > rawLimitTop){


digitalWrite(compR1, LOW);
pinMode(compR1, INPUT);
pinMode(compR2, OUTPUT);
digitalWrite(compR2, HIGH);
raw = analogRead(analogOhm);
Rn = R4;

Serial.println(raw);
Serial.print("ref 100k: ");
Serial.println(Rn);

if (raw < rawLimitLow || raw > rawLimitTop){


digitalWrite(compR2, LOW);
pinMode(compR2, INPUT);
pinMode(compR3, OUTPUT);
digitalWrite(compR3, HIGH);
raw = analogRead(analogOhm);
Rn = R3;

Serial.println(raw);
Serial.println("ref 10k");

if (raw < rawLimitLow || raw > rawLimitTop){


digitalWrite(compR3, LOW);
pinMode(compR3, INPUT);
pinMode(compR4, OUTPUT);
digitalWrite(compR4, HIGH);
raw = analogRead(analogOhm);
Rn = R2;

Serial.println(raw);
Serial.println("ref 1k");

if (raw < rawLimitLow || raw > rawLimitTop){


digitalWrite(compR4, LOW);
pinMode(compR4, INPUT);
pinMode(compR5, OUTPUT);
digitalWrite(compR5, HIGH);
raw = analogRead(analogOhm);
Rn = R1;

Serial.println(raw); // DEBUG
Serial.println("ref 100");// DEBUG
}
}
}
}

Vout = 5*(raw/1024);

Ru = (Rn*Vout)/(5-Vout);
Serial.print("Ru: "); // DEBUG
Serial.println(Ru); // DEBUG

String resOhm = OhmFormattingFunction(Ru);


delay(1000);

Serial.print("Resistenza da: "); // DEBUG


Serial.println(resOhm); // DEBUG

lcd.setCursor(0,1);
lcd.print(resOhm);
}

String OhmFormattingFunction(float Input) {


//FS 20200223 v0 - Ohm values formatting function **

String Result;

if (Input < 80) {


valore = (String(round(Input)));
suffisso = " ";
}
else if (Input < 800){
valore = (String(10*round(Input/10)));
suffisso = " Ohm";
}
else if (Input < 9000){
trans = float(round(Input/100))/10;
valore = (String(trans));
suffisso = " KOhm";
}
else if (Input < 90000){
valore = (String(10*round(Input/10000)));
suffisso = " KOhm";
}
else if (Input < 900000){
valore = (String(10*round(Input/10000)));
suffisso = " KOhm";
}
else {
valore = (String(round(Input/1000000)));
suffisso = " MOhm";
}
Result = valore + suffisso;
return Result;
}
187) Arduino Use Your Phone as a Voice Remote

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Bluetooth Low Energy (BLE)


Module (Generic) × 1
IR transmitter (generic)
× 1

IR receiver (generic)
× 1

ABOUT THIS PROJECT


In this project we will be making a simple device using which you can
actually speak with your TV no matter which brand or which model
your TV belongs to the device can be made universal to any device, yes
you can also make voice remote even for your ancient TV.
The project doesn't require any advanced programming anyone is
a basic knowledge in arduino can master this project easily. The price
of making is very cheap which is less than buying iR TV remote.
Let's start making!!!

Taking Data From IR TV Remote


USE CODE 1 PROVIDED
So this is our first step of our making we gonna make the initialisation
process that is we are going to collect the data stored in your IR remote
which your TV can understand using our IR Decoder and we are going
to use this decoded information in our device to use this data to
communicate with your TV. Thus this step proves that any TV that uses
an IR remote can be used in this project so there is no restrictionfor this
project that only it supports High end TV.
This step is actually very simple you are going to use your TV remote
to decode the data in the button which ever you want to use in the
device that is you can choose only the important buttons like increase
volume, increase channel, power, input.....
To decode the data you need to follow the below steps for each of the
buttons you want:
1. Make the circuit connections as shown in the picture above.
2. upload the code to the arduino which is given below (code1.ino).
3. Now choose which button you need to decode and open the serial
monitor on your arduino IDE software.
4. Flash the remote towards the IR receiver by pressing the button.
5. You will be getting a series of data on your serial monitor.
6. copy the entire content in the serial monitor and paste in a word pad
for later reference.
7. similarly collect the data for all the important buttons you want.
Making the Wireless IR Blaster
The project uses a mobile app to recognize the voice and decode it and
send the respective code to the arduino containing the Ir transmitter via
Bluetooth.
The circuit connection for the device is explained in the images
displayed above.
Thus the connections will be very simple and less or you can also use a
solder to avoid the usage of wires and reduce the size of the project.
You will be keeping this device in front of the tv's IR receiver.
Coding the Receiver Device
Open the code2 given below using your arduino IDE software.
In this try to read the comments given in the sides which will be
explaining the code clearly.Here you need to put in the entire set of
content that you have taken from your Ir remote and stored in a word
pad during your STEP3.
This is so simple, create a function for your button by giving a suitable
name for it and put in the data from teh word pad into the block
correspondingly.

Modifying the Android App


https://cdn.instructables.com/ORIG/F04/0F6P/JI4UCD2F/F040F6PJI4UCD2F.aia
I have created a basic app using the mit app inventor for doing the
speech recognition and sending the data to the arduino receiver via
Bluetooth.
You can use the same app only by making a few modifications in it to
suit your TV.
I have provided the editable format of my app which is operable at the
mit app inventor.
http://appinventor.mit.edu/explore/
sign up in the above link and open the app by clicking the import file
option.

The modifications to be performed are explained briefly below:


change the channel names which are rounded in the image 1 to your
liking.
The name you give here will be your voice command so you need to
speak this word inorder to activate the task.
Once the task is activated(say increase volume) then the code saved
in it will be transmitted to the arduino via bluetooth.
So you need to match the number in the app with the number on the
arduino receiver coding.
These are the main modifications to be performed you can also share
your own creativity in this.
you can also change the background and the icon of the
application make it suit your way and enjoy the app.
Enjoy Smartly!
Now you can enjoy the smart TV experience with any type of TV. Try
debugging your work if any error persists please let me know.
You need to keep the bluetooth on during the usage of the app.

SCHEMATICS

Bluetooth module

ir transmitter
ir decoder
CODE

ode 1Arduino
use in the first for decoding ir .

#define IRpin_PIN PIND


#define IRpin 2

// the maximum pulse we'll listen for - 65 milliseconds is a long time


#define MAXPULSE 65000

// what our timing resolution should be, larger is better


// as its more 'precise' - but too large and you wont get
// accurate timing
#define RESOLUTION 20

// we will store up to 100 pulse pairs (this is -a lot-)


uint16_t pulses[100][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing

void setup(void) {
Serial.begin(9600);
Serial.println("Ready to decode IR!");
}

void loop(void) {
uint16_t highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length

// while (digitalRead(IRpin)) { // this is too slow!


while (IRpin_PIN & (1 << IRpin)) {
// pin is still HIGH

// count off another few microseconds


highpulse++;
delayMicroseconds(RESOLUTION);

// If the pulse is too long, we 'timed out' - either nothing


// was received or the code is finished, so print what
// we've grabbed so far, and then reset
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;

// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= 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

Alphanumeric LCD, 16 x 2

× 1

Jumper wires (generic)


× 1

Tactile Switch, Top Actuated

× 4

Arduino UNO & Genuino UNO

× 1

Rotary potentiometer (generic)

× 1

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 <LiquidCrystal.h>
//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

GPRS shield SIM900


× 1

12V switching wall power supply


× 1

SparkFun Solder-able Breadboard - Mini


× 1

Female Header 8 Position 1 Row (0.1")


One with short pins, two with long pins to
stack on GPRS shield × 3

Male power Jack


× 2

Female power jack


× 2

9V battery (generic)

× 1

9V Battery Clip

× 1

Resistor 10k ohm

× 2

Resistor 5,6K ohm or 6,8k ohm


× 1

1N4007 – High Voltage, High Current Rated


Diode
× 2
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 <SoftwareSerial.h>

// 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
× 1
Any equivalent DS3231 IIC RTC
should work
Kuman 0.96 Inch Yellow Blue IIC
OLED Module I2c
× 1
Any equivalent 0.96 inch OLED
should work
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 Real-
time 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 <Wire.h>

// For the DS3231 Real time Clock Module (AT24C32 Module)


#include <DS1307RTC.h>

// 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<10)
{
hours = "0"+String(tm.Hour);
}
else
{
hours = String(tm.Hour);
}

if(tm.Minute<10)
{
minutes = "0"+String(tm.Minute);
}
else
{
minutes = String(tm.Minute);
}

// We're processing seconds "just in case", but not adding them to the small display

if(tm.Second<10)
{
seconds = "0"+String(tm.Second);
}
else
{
seconds = String(tm.Second);
}

str_time = hours + ":" + minutes;


}

void setup()
{
// Start Wire library for I2C
Wire.begin();
clearOLED();
dht.begin();
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Initialize();
}

void loop()
{
int i, median_index;

RTC.read(tm); // Get the date and time


monthStr(tm); // Convert the month from a number to Jan, Feb, Mar, etc
timeStr(tm); // Convert the time to strings

h = dht.readHumidity(); // Get Humidity value


t = dht.readTemperature(); // Get Temperature value

// Replace the oldest value with the newest just read by moving every element in
// the arrays up one and sticking this new value in the bottom.
for (i = 0 ; i < buff_size - 1 ; i++)
{
h_array[i] = h_array[i + 1];
t_array[i] = t_array[i + 1];
}
h_array[buff_size-1] = h;
t_array[buff_size-1] = t;

// Move them into the sort arrays


for (i = 0 ; i < buff_size ; i++)
{
h_array_sort[i] = h_array[i];
t_array_sort[i] = t_array[i];
}

// Sort them. Use quick and dirty bubble sort because it's a small number of data points
bubble_sort(h_array_sort, buff_size);
bubble_sort(t_array_sort, buff_size);

// Use the median of the last "buff_zize" readings for the display
median_index = buff_size / 2;
h = h_array_sort[median_index];
t = t_array_sort[median_index];
string_Temp = String(t,1); // Make temp a character string
string_Humid = String(h,1); // Make humid a character string

// Build first OLED line


str_year = tmYearToCalendar(tm.Year);
str_day = tm.Day;
str_day = str_day + "-";
str_month = str_month + "-";
temporary_string = " " + str_day + str_month + str_year + " " + str_time;
strcpy(OLED_string_1, temporary_string.c_str()); // Put date/time string in the first
character array

// Build second OLED line


temporary_string = "";
temporary_string = temporary_string + string_Temp + char(176) + "C "; // char(176) is
the degree symbol
temporary_string = temporary_string + string_Humid + " %";
strcpy(OLED_string_2, temporary_string.c_str()); // Put temperature/humidity string in
the second character array

sendstringstoDisplay(); // Display the median temperature and humidity


delay(5000); // Updates every 5 seconds
}

191) Arduino Raise the Volume with Remote Controlled


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

SG90 Micro-servo motor

× 1

Jumper wires (generic)


× 1

Infrared Receiver, Remote Control

× 1

RGB LCD Shield Kit, 16x2


Character Display
× 1

Breadboard (generic)

× 1

Resistor 1k ohm

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


About this project
The purpose of this project is to lower or decrease the volume of a radio
through a remote control with Arduino and to visualize the value on an
LCD display.
If is a button is pressed on an Arduino remote controller, the signal is
received by an IR sensor and elaborated with Arduino Uno.
When vol+ or vol- is held down, the Arduino will turn a servo on
clockwise or counter-clockwise, which will turn volume knob of my
stereo. The LCD display will show the volume percent and when the
volume is more then 80% will reveal, "too high!”
The box is made for my stereo and is showed in this picture
The circuit
Arduino checks the servo motor through the pin11, the IR receiver with 10
and the LCD display through the pins from 2 to 7. Every component needs
5V except the pin 15 of the display, which uses maximun 4.2V and needs
a resistence. The pin v0 (n°3) of the display connects to a potentiometer
that regulates the brightness of the screen. The following scheme is made
in Tinkercad.
The LCD display pins are connected with Arduino how in the code.

SCHEMATICS
CODE

#include <IRremote.h>
#include <Servo.h>
#include <LiquidCrystal.h>

Servo myservo;
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int receiver = 10;
IRrecv irrecv(receiver);
decode_results results;
int code=0;
int x;
int cont=0;
int volume=0;
int y=0;

void setup()
{
Serial.begin(9600);
irrecv.enableIRIn();
myservo.attach(11);
lcd.begin(16, 2);
lcd.clear();
}
void loop()
{
if (irrecv.decode(&results))
{
code=results.value;
Serial.println(code, HEX);
irrecv.resume();
switch(code)
{
case(0xFFFFA857):
cont=1;
x=x+3;
break;
case(0xFFFFE01F):
cont=0;
x=x-3;
break;
case(0xFFFFFFFF):
if(cont==1)x=x+4;
if(cont==0)x=x-4;
break;
default;
cont=2;
break;

}
x=constrain(x,3,180);
Serial.println(x);
myservo.write(x);
volume=map(x,3,180,0,100);
}
lcd.setCursor(8, 0);
lcd.print("VOLUME:");
lcd.setCursor(4, 1);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print(volume);
if(volume>80)
{
lcd.setCursor(7, 1);
lcd.print("too high!");
}
delay(50);
lcd.clear();
}
192) Arduino Clock

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

PCF8563
× 1

Crystal 32kHz
× 1

10K potentiometers
× 10

10k 1/4w resistor


× 10

Resistor 220 ohm

× 10

LCD 16x2
× 1

Breadboard 830 points with Wire


Kit × 1

ABOUT THIS PROJECT


1. Before you start
In this lesson will be used an LCD and real time clock, so take care to read
the lessons Arduino & LCDs and Real Time Clock (RTC)
PCF8563 before you start.
2. Schematic
The schematic is a merge of the two previous lessons so it is very simple.
The PCF8563 communicate with Arduino using TWI and when the data is
received the LCD is refreshed, showing the new time.
3. Set date and time
To set Date and Time use the following sketch:
/* Demonstration of Rtc_Pcf8563 Set Time.
* Set the clock to a time then loop over reading time and
* output the time and date to the serial console.
* I used a RBBB with Arduino IDE, the pins are mapped a
* bit differently. Change for your hw
* SCK - A5, SDA - A4, INT - D3/INT1
* After loading and starting the sketch, use the serial monitor
* to see the clock output.
* setup: see Pcf8563 data sheet.
* 1x 10Kohm pullup on Pin3 INT
* No pullups on Pin5 or Pin6 (I2C internals used)
* 1x 0.1pf on power
* 1x 32khz chrystal

#include <Wire.h>
#include <Rtc_Pcf8563.h>

//init the real time clock


Rtc_Pcf8563 rtc;

void setup()
{
//clear out the registers
rtc.initClock();
//set a time to start with.
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc.setDate(14, 6, 3, 1, 10);
//hr, min, sec
rtc.setTime(1, 15, 0);
}

void loop()
{
//both format functions call the internal getTime() so that the
//formatted strings are at the current time/date.
Serial.print(rtc.formatTime());
Serial.print("\r\n");
Serial.print(rtc.formatDate());
Serial.print("\r\n");
delay(1000);
}
4. The code
Now you can use your clock loading this sketch on your Arduino:
#include <Wire.h>
#include <Rtc_Pcf8563.h>

//init the real time clock


Rtc_Pcf8563 rtc;

// include the library code:


#include

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.print(" Arduino Clock!");
while(1500 - millis() > 0);
pinMode(13, OUTPUT);
}
SCHEMATICS

CODE

/* Demonstration of Rtc_Pcf8563 Set Time.


* Set the clock to a time then loop over reading time and
* output the time and date to the serial console.
*
* I used a RBBB with Arduino IDE, the pins are mapped a
* bit differently. Change for your hw
* SCK - A5, SDA - A4, INT - D3/INT1
*
* After loading and starting the sketch, use the serial monitor
* to see the clock output.
*
* setup: see Pcf8563 data sheet.
* 1x 10Kohm pullup on Pin3 INT
* No pullups on Pin5 or Pin6 (I2C internals used)
* 1x 0.1pf on power
* 1x 32khz chrystal
*
*/
#include <Wire.h>
#include <Rtc_Pcf8563.h>

//init the real time clock


Rtc_Pcf8563 rtc;

void setup()
{
//clear out the registers
rtc.initClock();
//set a time to start with.
//day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc.setDate(14, 6, 3, 1, 10);
//hr, min, sec
rtc.setTime(1, 15, 0);
}

void loop()
{
//both format functions call the internal getTime() so that the
//formatted strings are at the current time/date.
Serial.print(rtc.formatTime());
Serial.print("\r\n");
Serial.print(rtc.formatDate());
Serial.print("\r\n");
delay(1000);
}
193) Arduino 7 Segment LED Display Using a Shift Register

COMPONENTS AND SUPPLIES


Arduino Nano R3

× 1
74HC595 Shift Register
× 1

Solderless Breadboard Full Size

× 2

Jumper wires (generic)

× 1

Single Digit 7 Segment LED


Display
× 1
Any Single Digit 7 Segment LED
Display should work
Resistor 330 ohm

× 8
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


Introduction
This tutorial assumes you are somewhat familiar with 7 Segment LED
Displays and builds upon the 7 Segment LED Displays 101 -- How to
Make One Work tutorial. To complete this tutorial, you will need the
pinout for the 7 Segment LED Display you are using. If you do not
have this information, please see the previous tutorial.
Adding one or more shift registers to your project will conserve the
number of Arduino compatible I/O pins required to drive your 7
Segment LED Displays and can significantly reduce the power needed
for multiple digit displays.
Project Construction
Place one breadboard above the other as shown in the Frizing diagram
below. Some breadboards have matching slots and tabs that can be used
to lock them together, but this is not essential.
74HC595 Shift Register with 7 Segment LED Display
Arduino Uno or Nano Development Board
A 5VDC Arduino Uno or Nano with the ATMega328 microprocessor
can safely power this project, driving the 74HC595 Shift Register and
Toplite 5161BS 7 Segment LED Display used to develop this tutorial.
Any other Single Digit 7 Segment LED Display should be safe to use
as long as total current does not exceed 200mA. Leave the
development board powered off during project construction.
Connect the 5V pin of the development board to the top power rail of
the upper breadboard. Then connect a jumper from that power rail to
the bottom power rail of the lower breadboard. Wires connected to the
power rails are shown in red. Now connect grounds from the
development board to to top and bottom ground rails of the upper
breadboard. Wires connected to the ground rails are black.
74HC595 Shift Register
The 74HC595 Shift Register is an integrated circuit (IC) component
with a definite notch or dimple at one end. Place the 74HC595 on the
upper breadboard with the notch to your left so that the two rows of
pins are connected to the breadboard on opposite sides of the center
horizontal divide. Any printing on the top of the 74HC595 should
appear upright when the IC has been plugged into the breadboard as
shown in the above Fritzing diagram.
IC pins are commonly numbered counterclockwise starting with pin 1,
which is located to the left or below the dot or notch at one end. The
74HC595 follows this convention. Connect jumpers (shown in red)
from the top power rail of the upper breadboard to pins 10 (MR) and 16
(Vcc) of the 74HC595. Pin 16 supplies 5VDC power to the Shift
Register and holding Pin 10 (MR) HIGH with 5V prevents the register
from clearing.

74HC595 Shift Register Pinouts


Connect jumpers (shown in black) from pins 8 (GND) and 13 (OE) to
the bottom and top ground rails respectively of the upper breadboard.
Pin 8 is the 74HC595 Ground pin and by grounding pin 13, it is held
LOW to enable output from the Shift Register.
We will be using pins 4, 7 and 8 on an Arduino compatible Uno or
Nano microprocessor development board, although any of the other
available I/O pins could be used, if you prefer. The reason I use pins 4,
7 and 8 for shift registers is that these pins don't have any properties
other than Digital I/O, so by selecting them, I can reserve the more
versatile pins for other uses like interrupts, PWM or various serial and
buss communication protocols.
Connect the Arduino compatible development board to the 74HC595 as
follows:
Arduino pin 4 to 74HC595 pin 14 (DS) Serial Data input with a blue
wire
Arduino pin 7 to 74HC595 pin 12 (ST_CP) Latch pin with a green
wire
Arduino pin 8 to 74HC595 pin 11 ( SH_CP) Clock pin with a yellow
wire
7 Segment LED Display (single digit)
The particular display used in this tutorial is a TopLite 5161BS with a
Common Anode. In order to make this tutorial as general as possible, I
will refer to the Display pins by their individual segments (A-G and
Dp). Some displays are pinned out the same as the 5161BS, but many
are not and others may be of the Common Cathode variety. Do not
literally follow the Fritzing project diagram when connecting your
display to the 74HC595 shift register. If you are not sure what display
pins go to which segments, now would be a good time to review
my previous tutorial.
7 Segment LED Display Map
After you have mapped your displays pins to the above segment map,
make the following connections:
74HC595 pin 15 (Q0) to unused breadboard column next to
74HC595 pin 1 (orange wire)
From the jumper wire you just installed make a connection to the
Display pin corresponding to Segment A using a 330 Ohm resistor.
Any resistor value between 180 Ohm to 1,000 Ohm should work as
the idea is to protect the Display Segment LED by restricting
current.
Using 330 Ohm resistors and jumpers, connect the remaining Display
Segments:
74HC595 pin 1 (Q1) to resistor then jumper to Display pin
for Segment B
74HC595 pin 2(Q2) to resistor then jumper to Display pin
for Segment C
74HC595 pin 3(Q3) to resistor then jumper to Display pin
for Segment D
74HC595 pin 4(Q4) to resistor then jumper to Display pin
for Segment E
74HC595 pin 5(Q5) to resistor then jumper to Display pin
for Segment F
74HC595 pin 6(Q6) to resistor then jumper to Display pin
for Segment G
74HC595 pin 7(Q7) to resistor then jumper to Display pin
for Segment Dp
The last step of the construction phase of this project is to connect a
common pin on the Display to either the power or ground rail on the
breadboard. If you have a Common Anode Display, use a red jumper to
the power rail, otherwise connect a Common Cathode Display to the
ground rail using a black jumper. Double check your work and leave
the development board powered off.
Programming the Arduino IDE Sketch
The sketch is organized into four main sections; Global Declarations,
Setup, and the main Loop followed by two User Defined Functions.
Global Declarations
Constant Integers are given the descriptive
labels dataPin, latchPin and clockPin and assigned the values 4, 7 and 8
respectively. If you are using different pin assignments on your
project development board, change the values accordingly.
A Constant Char (single character) labeled common, is given either the
value 'a' for Common Anode Displays or 'c' for Common Cathode.
As written, the Sketch is set up for Common Anode Displays. If your
Display is of the Common Cathode type, comment out or delete the
Common Anode declaration line and uncomment the Common
Cathode line. In most cases, this will be the only change necessary
for the Sketch to run correctly.
A Boolean Variable, decPt, is initialized as true. This variable is used
to indicate if the Decimal Point Segment (Dp) is to be lit.
Setup
The Setup code block merely initializes the development project board
pins associated with the constant values
of dataPin, latchPin and clockPin for OUTPUT.
Loop
The Loop code block repeats endlessly until power is shut off or a
project component fails or is disconnected.
Every time the Loop begins, the value of the Global variable, decPt, is
either true or false. Whatever the value happens to be, it is changed from
true to false or vice versa so that the Display's Decimal Point segment is
only lit on every other pass through the Loop.
A for loop code block then runs 16 times, incrementing the value of the
local integer variable, i, from 0 to 15. Each value of i, is passed to the
User Defined Function, myfnNumToBits which returns the local byte
value, bits, an eight bit representation of all the Display Segments needed
to represent the Hexadecimal value of the variable i.
If decPt is true, the value of bits is modified by setting the Least
Significant Bit (LSB) to 1 using the Bitwise OR operator.
The User Defined Function, myfnUpdateDisplay is called with the
variable, bits, as an argument. When the Display has been updated by
the myfnUpdateDisplay function, the program waits for 1/2 second before
incrementing the value of i and repeating the for loop until the value of i is
greater than 15; then the whole Loop code block starts over.
User Defined Function
myfnUpdateDisplay is called from the for loop within the Loop code
block with a byte argument. Each of the 8 bits in the byte represents
one of the Display segments from A to Dp.
For Common Cathode Displays, if a bit value is 1, the associated
segment is to be lit, otherwise the bit is 0 and the segment is turned off.
The bits need to be reversed for Common Anode displays, so all 8 bit
values in the byte are flipped if the Global variable, common equals 'a',
changing 1s to 0s and 0s to 1s using the BitWise XOR (^) operator with a
B11111111 bit mask.
The Arduino compatible development board latchPin is set LOW before
the bits are being sent into the 74HC595's registers. Then the
shiftOut(dataPin, clockPin, LSBFIRST, byte) function is called to transfer
the bits. Finally, latchPin is set HIGH and the Display should show the
appropriate alphanumeric character.
Program control is then returned to the for loop inside the Loop code
block.

SCHEMATICS
CODE

* Simple example of using Shift Register with a


* Single Digit Seven Segment LED Display
*/
// Globals
const int dataPin = 4; // blue wire to 74HC595 pin 14
const int latchPin = 7; // green to 74HC595 pin 12
const int clockPin = 8; // yellow to 74HC595 pin 11

/* uncomment one of the following lines that describes your display


* and comment out the line that does not describe your display */
const char common = 'a'; // common anode
//const char common = 'c'; // common cathode

bool decPt = true; // decimal point display flag

void setup() {
// initialize I/O pins
pinMode(dataPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}

void loop() {
decPt = !decPt; // display decimal point every other pass through loop

// generate characters to display for hexidecimal numbers 0 to F


for (int i = 0; i <= 15; i++) {
byte bits = myfnNumToBits(i) ;
if (decPt) {
bits = bits | B00000001; // add decimal point if needed
}
myfnUpdateDisplay(bits); // display alphanumeric digit
delay(500); // pause for 1/2 second
}
}

void myfnUpdateDisplay(byte eightBits) {


if (common == 'a') { // using a common anonde display?
eightBits = eightBits ^ B11111111; // then flip all bits using XOR
}
digitalWrite(latchPin, LOW); // prepare shift register for data
shiftOut(dataPin, clockPin, LSBFIRST, eightBits); // send data
digitalWrite(latchPin, HIGH); // update display
}

byte myfnNumToBits(int someNumber) {


switch (someNumber) {
case 0:
return B11111100;
break;
case 1:
return B01100000;
break;
case 2:
return B11011010;
break;
case 3:
return B11110010;
break;
case 4:
return B01100110;
break;
case 5:
return B10110110;
break;
case 6:
return B10111110;
break;
case 7:
return B11100000;
break;
case 8:
return B11111110;
break;
case 9:
return B11110110;
break;
case 10:
return B11101110; // Hexidecimal A
break;
case 11:
return B00111110; // Hexidecimal B
break;
case 12:
return B10011100; // Hexidecimal C or use for Centigrade
break;
case 13:
return B01111010; // Hexidecimal D
break;
case 14:
return B10011110; // Hexidecimal E
break;
case 15:
return B10001110; // Hexidecimal F or use for Fahrenheit
break;
default:
return B10010010; // Error condition, displays three vertical bars
break;
}
}
194) Arduino Smart Phone Controlled Led Matrix
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Male/Female Jumper Wires

× 1

HC-05 Bluetooth Module


× 1

LED Dot Matrix Display, Red

× 1

Maxim Integrated
MAX7219/MAX7221 LED Display
Drivers × 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

:How To Control Led Matrix With SmartPhone:-


Hi everyone, my name is Rohan Barnwal and in this project, I taught
that how to control led matrix with your smartphone it's very easy to
make you need
1.Led matrix of 8x8 which should be connected with MAX7219 Driver
2.HC-05 Module
3. Arduino Uno Board
4. Smartphone
SCHEMATICS

CODE

#include <LedControl.h>

int DIN = 12;


int CS = 10;
int CLK = 11;
int row=0;
int col=0;
int temp=0;
int data=0;

LedControl lc=LedControl(DIN,CLK,CS,1);

void setup()
{
lc.shutdown(0,false);
lc.setIntensity(0,5);
lc.clearDisplay(0);
Serial.begin(9600);
}

void loop()
{
if(Serial.available() > 0)
{
data = Serial.read();// it returns ascii value if we send one in the phone
if(data < 96)
{
if(temp==0)
{
row=data-48;
temp=1;
}
else
col=data-48;
}

else if(data=='n')
{
lc.setLed(0,row,col,true);
Serial.println('n');
Serial.println(row);
Serial.println(col);
temp=0;
}
else if(data=='f')
{
lc.setLed(0,row,col,false);
Serial.println('f');
Serial.println(row);
Serial.println(col);
temp=0;
}

else if(data=='r')
lc.clearDisplay(0);
}

195) Arduino Brasileirinho Tone


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Speaker: 0.25W, 8 ohms

ABOUT THIS PROJECT


I'm exploring its musical applications. At this stage of learning I am
using the tone function to play a two-part piece.
I made the musical arrangement in the Finale software, and then I made
the MIDI file into Arduino code through
http://greenlightgo.org/projects/midi-to-arduino/ Then I set up a very
simple circuit with only one speaker on pin 4.

SCHEMATICS
CODE

/**
Peça musical executada pela função Tone do Arduino. Execução monofônica. (Musical
piece performed by Arduino Tone function. Monophonic playback.)
Título(Title): Brasileirinho.
Música (Music): Waldir Azevedo.
Arranjo (Arrangement): Glauber Santiago.
Circuito (Circuit): Autofalante de 8 ohm no pino 4 (8 ohm speaker on digital pin 8).
**/

#define msPerTick 0.4 //Andamento(Tempo)

void setup() {
pinMode(4, OUTPUT);

doPerformance();
}

void loop() {
}

void doPerformance() {
tone(4, 494);

delay(102 * msPerTick);

noTone(4);

delay(154 * msPerTick);

tone(4, 494);

delay(205 * msPerTick);

noTone(4);

delay(307 * msPerTick);

tone(4, 494);

delay(102 * msPerTick);
noTone(4);

delay(410 * msPerTick);

tone(4, 392);

delay(205 * msPerTick);

noTone(4);

delay(307 * msPerTick);

tone(4, 494);

delay(102 * msPerTick);

noTone(4);

delay(154 * msPerTick);

tone(4, 587);

delay(205 * msPerTick);

noTone(4);

delay(819 * msPerTick);

tone(4, 294);

delay(205 * msPerTick);

noTone(4);

delay(819 * msPerTick);

tone(4, 147);

delay(205 * msPerTick);

noTone(4);

delay(307 * msPerTick);

tone(4, 988);
delay(512 * msPerTick);

noTone(4);
tone(4, 988);

delay(512 * msPerTick);

noTone(4);
tone(4, 988);

delay(384 * msPerTick);

tone(4, 196);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(128 * msPerTick);

tone(4, 147);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);
noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 196);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(128 * msPerTick);

tone(4, 147);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 196);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(128 * msPerTick);

tone(4, 147);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 196);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(128 * msPerTick);

tone(4, 147);
delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 196);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(128 * msPerTick);

tone(4, 147);

delay(128 * msPerTick);
noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 196);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(128 * msPerTick);
tone(4, 294);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 880);

delay(256 * msPerTick);

noTone(4);
tone(4, 831);

delay(128 * msPerTick);

tone(4, 392);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 233);

delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(256 * msPerTick);
noTone(4);
tone(4, 294);

delay(256 * msPerTick);

noTone(4);
tone(4, 233);

delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(256 * msPerTick);

noTone(4);
tone(4, 294);

delay(256 * msPerTick);

noTone(4);
tone(4, 233);

delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(256 * msPerTick);

noTone(4);
tone(4, 294);

delay(256 * msPerTick);

noTone(4);
tone(4, 233);

delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(128 * msPerTick);

tone(4, 147);
delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 294);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(128 * msPerTick);

tone(4, 196);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);
delay(128 * msPerTick);

tone(4, 185);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 165);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);
delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(128 * msPerTick);

tone(4, 147);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 196);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);
noTone(4);
tone(4, 932);

delay(128 * msPerTick);

tone(4, 175);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 156);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(128 * msPerTick);

tone(4, 147);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 196);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(128 * msPerTick);

tone(4, 185);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 165);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);
delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 988);

delay(128 * msPerTick);

tone(4, 147);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 988);

delay(256 * msPerTick);

noTone(4);
tone(4, 932);

delay(256 * msPerTick);

noTone(4);
tone(4, 880);

delay(256 * msPerTick);

noTone(4);
tone(4, 831);

delay(128 * msPerTick);

tone(4, 98);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);
delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(256 * msPerTick);

noTone(4);
tone(4, 247);

delay(256 * msPerTick);

noTone(4);
tone(4, 233);

delay(256 * msPerTick);

noTone(4);
tone(4, 220);

delay(256 * msPerTick);

noTone(4);
tone(4, 208);

delay(256 * msPerTick);

noTone(4);
tone(4, 196);

delay(256 * msPerTick);

noTone(4);
tone(4, 185);

delay(256 * msPerTick);
noTone(4);
tone(4, 165);

delay(256 * msPerTick);

noTone(4);
tone(4, 147);

delay(256 * msPerTick);

noTone(4);
tone(4, 98);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 659);

delay(256 * msPerTick);

noTone(4);
tone(4, 698);

delay(128 * msPerTick);

tone(4, 294);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 740);

delay(256 * msPerTick);

noTone(4);
tone(4, 698);

delay(256 * msPerTick);
noTone(4);
tone(4, 659);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 220);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 659);

delay(256 * msPerTick);

noTone(4);
tone(4, 698);

delay(256 * msPerTick);

noTone(4);
tone(4, 740);

delay(256 * msPerTick);

noTone(4);
tone(4, 698);

delay(128 * msPerTick);

tone(4, 294);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 659);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(256 * msPerTick);

noTone(4);
tone(4, 659);

delay(256 * msPerTick);

noTone(4);
tone(4, 698);

delay(128 * msPerTick);

tone(4, 220);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 740);

delay(256 * msPerTick);

noTone(4);
tone(4, 698);

delay(256 * msPerTick);

noTone(4);
tone(4, 659);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 294);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);
delay(256 * msPerTick);

noTone(4);
tone(4, 740);

delay(256 * msPerTick);

noTone(4);
tone(4, 659);

delay(256 * msPerTick);

noTone(4);
tone(4, 587);

delay(128 * msPerTick);

tone(4, 196);

delay(128 * msPerTick);

noTone(4);
noTone(4);
tone(4, 784);

delay(256 * msPerTick);

noTone(4);
tone(4, 740);

delay(256 * msPerTick);

noTone(4);
tone(4, 659);

delay(256 * msPerTick);
...

This file has been truncated, please download it to see its full contents.
196) Arduino sCOOp-4-b1l1tY Meter

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

Resistor 22.1 ohm

× 8
Resistor 10k ohm

× 2

SparkFun Pushbutton switch 12mm

× 2

Capacitor 100 µF

× 1

Servos (Tower Pro MG996R)


× 1

LED (generic)

× 8

Hydrargyrum-switch
I have used a mercury switch as it × 1
is more sensitive, but any similar
tilt switch would do
Rotary potentiometer (generic)

× 1

9V battery (generic)

× 1
9V Battery Clip

× 1

Breadboard (generic)
a larger one would be nice but the
× 1
project fits on the small one
included un the starter kit
Arduino Proto Shield
This or any other shields that fit
UNO are necessary if you want to 1
×
build the physical device (if you
just like to build the prototype a
breadboard will suffice)
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
(optional) only if you want to create the
actual device, if you build on a breadboard it
won't be necessary
Laser cutter (generic)
(optional) only if you want to create the
actual device, if you build on a breadboard it
won't be necessary
Cardboard, markers, scissors, cutter
to design your display
Wood or plastic board
(optional) To build the case with the laser
cutter

ABOUT THIS PROJECT

We were having a dinner night as we had done many times, when one
of us, referring to a recent acquaintance said: "I wonder whether it
would be a good idea to have sex with that person...".
The scopability challenge (later renamed sC00p-4-b1l1tY) was set. Was
there such a thing? Could a machine say whether it is a good idea to get
laid? We thought so.

The first version


At first we were under the impression that responding to that question
was only a matter of numbers, so we came up with a formula that took
a lot of factors into account
An early version of the sC00p-4-b1l1tY index

The formula brought together attraction (fi), empathy (sigma), sexual


abstinence (alpha), long-term relationship projections (ro), nagging
probability (Pet), and some random factor (G): with a result of more
than 70%, getting laid with the target subject would be increasingly
recommendable.
We tested it in a number of occasions, and we decided we wanted
more: where was the magic? What about that instant connection
between two people? How could we take that into our algorithm?

The physical device


Well, Arduino made it possible!
We have created a physical device that two subjects can hold and,
following some simple instructions, use to find if they should
eventually conjugate.
We had run many prototyping sessions, to determine what components
should be included and how they should interact with users,
A prototype of the physical device
Once the prototype was completed we built a nice laser-cut case and
soldered all the components onto a proto-shield.
The final version of the device
The inside
You can assemble this project the way you like, but if you want to take
a look at what we did, here are some pics:
Components soldered on an Arduino UNO Shield, note the mercury tilt
switch at the bottom
The rear of the front panel
The open box

How does it work


When thinking about hitting on someone, there are four main questions
that people ask themselves. Our device tries to answer them (in its own
particular way):
Is it the right time? Subjects are supposed to press one button each,
keep them pressed as long as they like and then try to release them
simultaneously. The system measures the time difference of the button
release and grades their timing.
What would others think? Subjects must ask a third person to turn a
knob clockwise, to express the appropriateness of their carnal
conjunction towards society. A fully turned knob means maximum
appropriateness.
Can you both handle it? Subjects are supposed to keep the device still
and aligned for a few seconds. A tilt sensor counts how many times the
device is tilted and grades their inne balance.
Is this really meant to be? Greeks used to call it tuxh, the will of the
Gods that affects all human beings. In our case is a random number that
symbolises what cannot be predicted.
After each phase, the four LEDs give a basic idea of how each step was
graded, and when they are all completed the servo motor will point the
arrow to the final grade, or sC00p-4-b1l1tY index. With a result of 70%
or more... be fruitful and multiply!

SCHEMATICS
CODE
/**
* Previous versions:
* 0.9
* - testing physical implementation
* - fixed servo angles offsets
* - fixed tuxh random number problem using randomSeed()
* - made all comments in english
* 0.8
* - decided for tilt sensor instead of capacity
* 0.7
* - added tuxh factor
* - added phase LED indicators
* - decided to use capacity sensor for body input
* 0.6
* - added potentiometer feature
* - split file into tabs
* - added function documentation
* - restructured build system so that is modular
* 0.5
* - new concept with servo motor and button release millis difference
*/

#include <Servo.h>
//tilt vars
int tiltPin = 13;
//pot vars
int potPin = A0;
int currentPotValue = 0;
int previousPotValue = 0;
//LEDs vars
int green1 = 8;
int green2 = 9;
int yellow = 10;
int red = 11;
int phase1 = 4;
int phase2 = 5;
int phase3 = 6;
int phaseF = 7;
//Servo vars
int angle;
int servoPin = 12;
Servo myServo;
//switches vars
int buttonSx = 3;
int buttonDx = 2;
int buttonRelSx = 0;
int buttonRelDx = 0;
int currentSx = LOW;
int currentDx = LOW;
bool markSx = false;
bool markDx = false;
//global vars
int programPhase = 0;
int timeFactor = 0;
int potFactor = 0;
int tiltFactor = 0;
int tuxhFactor = 0;

void setup() {
Serial.begin(9600);
runTests();
}
void loop() {
currentSx = digitalRead(buttonSx);
currentDx = digitalRead(buttonDx);
programPhase = 0;
digitalWrite(phase1,HIGH);

//program starts by pressing both switches


while(currentSx == HIGH && currentDx == HIGH)
{
programPhase = 1;
readSwitches();
}

if(programPhase == 1) //calc. time factor


{
timeFactor = calculateTimeFactor();
//lits meters
meterResult(timeFactor,50,85);
delay(5000);
//turns meters off and proceeds to next phase
allLedState(LOW);
programPhase++;
}
if (programPhase ==2) // potentiometer
{
digitalWrite(phase2,HIGH);
potFactor = calculatePotFactor();
//lits meters
meterResult(potFactor,50,85);
delay(5000);
//turns meters off and proceeds to next phase
allLedState(LOW);
programPhase++;
}

if(programPhase == 3) //tilt sensor


{
digitalWrite(phase3,HIGH);
tiltFactor = calculateTiltFactor();
//lits meters
meterResult(tiltFactor,50,85);
delay(5000);
allLedState(LOW);
programPhase++;
}

if(programPhase == 4) //tuxh factor


{
digitalWrite(phaseF,HIGH);
delay(5000);
tuxhFactor = calculateTuxhFactor();
meterResult(tuxhFactor,50,85);
delay(5000);
allLedState(LOW);
programPhase++;
}
if(programPhase == 5) //final calculation and display
{
ledBlink(phaseF);
//calc. scopability
int index = calculateScopability(timeFactor,potFactor, tuxhFactor, tiltFactor);
//moves servo
showFinalResult(index);
digitalWrite(phaseF,HIGH);
delay(7000);
//returns servo
moveServo(20,false);
allLedState(LOW);
programPhase = 0;
Serial.println("Calcolo concluso");
}
// loop restarts
}

197) Arduino Grid Lock Puzzle

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1
SparkFun Button Pad 4x4 - LED
Compatible
× 1

Maxim Integrated
MAXREFDES99# MAX7219
Display Driver Shield × 1

ABOUT THIS PROJECT

Unlock each of 16 (4x4) locks to crack the bigger lock. Associated 4x4
buttons can be used to flip the state either horzontally or vertically.
Note either complete row or column of LEDs will flip its state not
individual.
SCHEMATICS
CODE
#include <Keypad.h> //keypad library
#include <LedControl.h>
const byte ROWS = 4; //four rows ; //declare rows
const byte COLS = 4; //four columns //declare columns
char keys[ROWS][COLS] = { //declare 2 dimensional array
to map keys
{'M', 'N', 'O', 'P'},
{'I', 'J', 'K', 'L'},
{'E', 'F', 'G', 'H'},
{'A', 'B', 'C', 'D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row
pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9}; //connect to the column
pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


//create instance of Keypad called keypad

int DIN = 12;


int CS = 11;
int CLK = 10;
LedControl lc = LedControl(DIN, CLK, CS, 0);

int FIVER[4][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
int r, c, i, j;
int flag = 1;

void setup() {
Serial.begin(9600);
lc.shutdown(0, false); //The MAX72XX is in power-saving mode on startup
lc.setIntensity(0, 1); // Set the brightness to maximum value
lc.clearDisplay(0); // and clear the display
randomSeed(analogRead(0));
}

void loop() {
if (flag == 1) {
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
FIVER[i][j] = random(0, 2);
}
}

flag = 0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (FIVER[i][j] == 1) {
lc.setLed(0, 2 * i, 2 * j , true);
lc.setLed(0, 2 * i + 1, 2 * j , true);
lc.setLed(0, 2 * i, 2 * j + 1 , true);
lc.setLed(0, 2 * i + 1, 2 * j + 1 , true);
}
if (FIVER[i][j] == 0) {
lc.setLed(0, 2 * i, 2 * j , false);
lc.setLed(0, 2 * i + 1, 2 * j , false);
lc.setLed(0, 2 * i, 2 * j + 1 , false);
lc.setLed(0, 2 * i + 1, 2 * j + 1 , false);
}
}
}
}

char key = keypad.getKey(); //use keypad.getKey function to


//to define the value of Char variable key

if (key == 'A') {
r = 0;
c = 0;
}
if (key == 'B') {
r = 0;
c = 1;
}
if (key == 'C') {
r = 0;
c = 2;
}
if (key == 'D') {
r = 0;
c = 3;
}
if (key == 'E') {
r = 1;
c = 0;
}
if (key == 'F') {
r = 1;
c = 1;
}
if (key == 'G') {
r = 1;
c = 2;
}
if (key == 'H') {
r = 1;
c = 3;
}
if (key == 'I') {
r = 2;
c = 0;
}
if (key == 'J') {
r = 2;
c = 1;
}
if (key == 'K') {
r = 2;
c = 2;
}
if (key == 'L') {
r = 2;
c = 3;
}
if (key == 'M') {
r = 3;
c = 0;
}
if (key == 'N') {
r = 3;
c = 1;
}
if (key == 'O') {
r = 3;
c = 2;
}
if (key == 'P') {
r = 3;
c = 3;
}

if (key) {
for (i = 0; i < 4; i++) {
FIVER[i][c] = 1 - FIVER[i][c];
}
for (i = 0; i < 4; i++) {
FIVER[r][i] = 1 - FIVER[r][i];
}
FIVER[r][c] = 1 - FIVER[r][c];

for (i = 0; i < 4; i++) {


for (j = 0; j < 4; j++) {
if (FIVER[i][j] == 1) {
lc.setLed(0, 2 * i, 2 * j , true);
lc.setLed(0, 2 * i + 1, 2 * j , true);
lc.setLed(0, 2 * i, 2 * j + 1 , true);
lc.setLed(0, 2 * i + 1, 2 * j + 1 , true);
}
if (FIVER[i][j] == 0) {
lc.setLed(0, 2 * i, 2 * j , false);
lc.setLed(0, 2 * i + 1, 2 * j , false);
lc.setLed(0, 2 * i, 2 * j + 1 , false);
lc.setLed(0, 2 * i + 1, 2 * j + 1 , false);
}
}
}
}
}

198) Arduino Digital Temperature


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Temperature Sensor

× 1

Adafruit Standard LCD - 16x2


White on Blue
× 1

Single Turn Potentiometer- 10k


ohms
× 1

Breadboard (generic)

× 2

Male/Male Jumper Wires


× 2

Ethernet Cable
× 1

ABOUT THIS PROJECT

The project is a temperature sensor made with an Arduino UNO and


LM35 sensor and a few other components. The main aim of the project is
to detect the temperature of the surroundings and display it on the LCD.
The working of the project starts with the LM35 sensor that senses the
change in temperature of the surrounding, and uses that temperature
difference to produce a voltage signal which is processed by the Arduino
to give a digital output displaying the temperature of the given
surrounding.
Connections
The connections to be made are given below:
Connect LCD PIN 1 to Ground and PIN 2 to Supply respectively.
Connect LCD PIN 3 to the 10K Potentiometer and connect rest of the
terminals to the ground.
Connect LCD PIN 15 to Ground and PIN 16 to Supply respectively.
Connect LCD PINS D4,D5,D6 and D7 to PINS 5 - 2 of the Arduino.
Connect LCD PIN 4(RS) to PIN 7 of the Arduino.
Connect LCD PIN 5(RW) to Ground.
Connect LCD PIN 6(E) to PIN 6 of the Arduino.
Attach the LM35 to the Bread Board.
Take the output of the LM35 i.e. PIN 2 of the LM35 and connect it to
the Analog Input Ao of the Arduino.
The Rest of the Connections made are to connect the Two Breadboards
together.
Connections
SCHEMATICS
CODE
#include<LiquidCrystal.h>
LiquidCrystal lcd(7,6,5,4,3,2);

const int Sensor = A0;


byte degree_symbol[8] =
{
0b00111,
0b00101,
0b00111,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000
};
void setup()
{
pinMode(Sensor, INPUT);
lcd.begin(16,2);
lcd.createChar(1, degree_symbol);
lcd.setCursor(0,0);
lcd.print(" Digital ");
lcd.setCursor(0,1);
lcd.print(" Thermometer ");
delay(4000);
lcd.clear();
}
void loop()
{

float temp_reading=analogRead(Sensor);
float temperature=temp_reading*(5.0/1023.0)*100;
delay(10);

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temperature in C");
lcd.setCursor(4,1);
lcd.print(temperature);
lcd.write(1);
lcd.print("C");
delay(1000);
}
199) Arduino Button

COMPONENTS AND SUPPLIES


Arduino 101 & Genuino 101

× 1

LED (generic)

× 1
SparkFun Pushbutton switch
12mm
× 1

Resistor 100 ohm

× 1

Resistor 10k ohm

× 1

Jumper wires (generic)

× 1

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

This project adds user input: a way to send a message to your Arduino, in
the language of hardware.
This sketch includes a great description of the circuit right in the opening
comments. Hook it up like so:
Notice how the LED's part of the circuit looks now. Most breadboards
have power and ground rails running their entire length. That makes it
easier to hook up circuits with just a single wire for each running back to
your controller. So, both the resistor from the button and the LED are
hooked back into this ground rail – instead of taking up both of the
Arduino's GND pins.
The resistor we've just added is a pulldown resistor. Our code is going to
check to see whether or not our digital pin 2 is connected to power, via the
button-press. But while unconnected, the pin's value floats somewhere
between HIGH (powered) and LOW (grounded). So, we let a bit of power
flow to the ground pin all the time, through this 10 kΩ resistor, which
"pulls it down" LOW. But when the button is pressed, power starts
flowing between the 5V pin and pin 2, so it goes HIGH.
CODE
This time, we begin with some declarations of different variables that we'll
be using. In the Blink sketch, if you wanted to change which pin the LED
was on, you had to change pin 13 in three different places. This time, we
tell the Arduino that we'll be using "buttonPin" to represent pin 2, and
"ledPin" to represent pin 13. Now, anytime we swap things around
physically, we just need to change that pin number in one place.
Those variables are going to stay the same the whole time the program is
running, so we call them constants – hence the const int. The other
variable we have will change to reflect our button-pressing, so it's just a
plain int.
This time, we've got INPUTs (button) and OUTPUTs (LED) in the setup
section.
In our loop, the first thing we do is check pin 2 to see whether it's HIGH or
LOW, using digitalRead. Then, depending on the result, we use an if/else
statement to trigger the right action. If it's HIGH (button pressed), set the
LED HIGH as well. Else (otherwise), set the LED LOW.
FYI, you can have more than two conditions – in which case, you tell it
"if the button is on, then turn the LED on; else if the button is not pressed,
then turn the LED off; else (say the button has ceased to exist or
Schrödinger is visiting) shrug your shoulders and do nothing."
Alternate circuit
There's a slightly simpler way to hook up this circuit, using the Arduino's
built-in pullup resistors. As you might suspect, these are the opposite of
pulldown resistors: they let a small amount of power flow between the
voltage source and the pin, without you making any physical connections,
so that the pin is normally held HIGH unless you've connected it to
ground. Super convenient!
All you'll need to do is change the button's type to INPUT_PULLUP, and
then connect the button directly to pins d2 and GND – no external resistor
needed.
As you might suspect, this swaps the Arduino's behavior. Since the pin is
normally HIGH now, the LED will stay on until you press the button. So,
you can switch around your conditions:
if (buttonState == LOW) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
Adapt this
So, in this case we used a button, but that's just one kind of digital input!
What else can you use?
Switch – Add physical control to toggle different sections of code.
Reed switch – Sense whether a door is open or closed, using these two-
part magnetic switches.
Wires – You don't even need a "real" button... tape two wires or pieces of
metal to different surfaces and detect when they come into contact. I once
built a horrible instrument this way, using weighted tinfoil balls to connect
two wires as a primitive switch.
Also, see the code below for a LATCHING / TOGGLE version – a button
that stays "pressed" until you hit it again.

SCHEMATICS

arduino-button.png
arduino-button-with-pullup.png
CODE
Button": Arduino example sketch
/*
Button
Turns on and off a light emitting diode(LED) connected to digital
pin 13, when pressing a pushbutton attached to pin 2.

The circuit:
* LED attached from pin 13 to ground
* pushbutton attached to pin 2 from +5V
* 10K resistor attached to pin 2 from ground
* Note: on most Arduinos there is already an LED on the board
attached to pin 13.
*/

// constants won't change. They're used here to


// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin

// variables will change:


int buttonState = 0; // variable for reading the pushbutton status

void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}

void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);

// check if the pushbutton is pressed.


// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
} else {
// turn LED off:
digitalWrite(ledPin, LOW);
}
}

LatchingButtonC/C++
A latching button: push once, LED turns on. Push again, LED turns
off. Includes a simple debouncer, so you don't have to worry too much
about how quickly you let go.
/*
Button
Turns on and off a light emitting diode(LED) connected to digital
pin 13, when pressing a pushbutton attached to pin 2.
The circuit:
* LED attached from pin 13 to ground
* pushbutton attached to pin 2 from +5V
* 10K resistor attached to pin 2 from ground
* Note: on most Arduinos there is already an LED on the board
attached to pin 13.
This example code is in the public domain.
*/

// set pin numbers:


const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin

// variables will change:


int buttonState = 0; // variable for reading the pushbutton status

void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}

void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);

// check if the pushbutton is pressed.


// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// toggle the LED state:
digitalWrite(ledPin, !digitalRead(ledPin);
// debounce:
delay(150);
}
}

200) DIY Arduino Fire Alarm System At Home


COMPONENTS AND SUPPLIES

Arduino Mega 2560 & Genuino


Mega 2560
× 1

Buzzer

× 1

flame sensor
× 1

Jumper wires (generic)


× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Build your Fire Alarm System at home with Arduino UNO. In this
tutorial, you will learn all steps to DIY Arduino fire alert system by
yourself. In this project, we need IR based flame sensor to detect firelight,
and it gives a signal to Arduino where buzzer connected to provide us with
the output as fire alert.
There is two type of flame sensors available one is Analog and other
Digital. Some sensor has both feature you can use easily just need little bit
changes on the sketch, not an issue at all. We will use both sensors and
here will be both source code available in the relevant section.
Arduino Fire Alarm System:
Build fire alarm or fireplace detector the use of Flame sensor and Arduino
board. The sensor mainly detects IR (Infra purple) light wavelength
between 760 nm – 1100 nm (nanometer) that emitted from fire flame.
Most of the fire sensors got here with the YG1006 sensor which is an
excessive velocity and excessive sensitive NPN silicon photograph
transistor. It’s miles included with black epoxy, for the reason that sensor
is touchy to infrared radiation. Through using this concept assignment you
can recognize the way to screen and alert approximately hearth flame, it is
maximum appropriate for fireplace combating robotic, fire alarm and so
forth.
What you will need:
Arduino UNO ( Any)
Flame Sensor.
Buzzer.
Jumper wires.
9V supply.
The cost is around about ten bucks for this fire alarm system. You can but
all the stuff from any online site like Amazon, eBay, Aliexpress…
Flame Sensor circuit diagram:
Now you need to wiring all the components with each other correctly. See
below for both type of sensors.
If you have Digital sensor connect as per shown in the image.

In case you have A0 (Analog sensor) then wiring will be as in the picture.

Source code for Flame sensor:


Code for Digital flame sensor. (D0)
// http://www.mrmodder.com visits for more Arduino Projects //
int Buzzer = 13; // Use buzzer for alert
int FlamePin = 2; // This is for input pin
int Flame = HIGH; // HIGH when FLAME Exposed

void setup() {
pinMode(Buzzer, OUTPUT);
pinMode(FlamePin, INPUT);
Serial.begin(9600);
}

void loop() {
Flame = digitalRead(FlamePin);
if (Flame== HIGH)
{
Serial.println("HIGH FLAME");
digitalWrite(Buzzer, HIGH);
}
else
{
Serial.println("No flame");
digitalWrite(Buzzer, LOW);
}
}
Source Code for A0 Analog flam sensor.
// http://www.mrmodder.com visits for more Arduino Projects //
const int analogPin = A0; // Flame Sensor (A0) to Arduino analog input
pin A0
const int BuzzerPin = 13; // Buzzer output pin
const int threshold = 400; // Flame level threshold (You can vary the
value depends on your need)

void setup() {

pinMode(BuzzerPin, OUTPUT);
// initialize serial communications:
<b>Serial</b>.begin(9600);
}

void loop() {
// read the value of the Flame Sensor:
int analogValue = analogRead(analogPin);
<b>Serial</b>.println(analogValue); //serial print the FLAME sensor
value

if (analogValue &gt; threshold) {


digitalWrite(BuzzerPin, HIGH);
<b>Serial</b>.print("High FLAME");
}
else if (analogValue = threshold){
<b>Serial</b>.print("Low FLAME");
digitalWrite(BuzzerPin, HIGH);
delay(400);
digitalWrite(BuzzerPin, LOW);
}
else {
digitalWrite(BuzzerPin, LOW);
<b>Serial</b>.print("No flame");
}

delay(1);
}
Upload the relevant code to Arduino Board test flame sensor it can detect
fire from according to my testing maximum 3 feet. However, it depends
on sensor quality it may be different on your sensor.

SCHEMATICS
CODE
int Buzzer = 13; // Use buzzer for alert
int FlamePin = 2; // This is for input pin
int Flame = HIGH; // HIGH when FLAME Exposed

void setup() {
pinMode(Buzzer, OUTPUT);
pinMode(FlamePin, INPUT);
Serial.begin(9600);

void loop() {
Flame = digitalRead(FlamePin);
if (Flame== HIGH)
{
Serial.println("HIGH FLAME");
digitalWrite(Buzzer, HIGH);
}
else
{
Serial.println("No flame");
digitalWrite(Buzzer, LOW);
}
}
201) How to Build a DIY Arduino Smart Home Hub with 1Sheeld

COMPONENTS AND SUPPLIES

1Sheeld

× 1
Ultrasonic Sensor - HC-SR04
(Generic) × 1

Seeed Grove - Gas Sensor(MQ2)

× 1

Relay Module (Generic)


× 1

5 mm LED: Red

× 1

Resistor 330 ohm

× 1

SparkFun Pushbutton switch 12mm

× 1

DHT22 Temperature Sensor

× 1

Servo Module (Generic)


× 1

Slide Switch
× 1

18650 battery
× 2

18650 dual battery box


× 1

Solderless Breadboard Half Size

× 1

Doom push button


× 1

Male/Female Jumper Wires

× 19

Male/Male Jumper Wires


× 10

IR transmitter diode
× 1

IR receiver module
× 1

Apple iPhone

× 1
Android device
× 1

Arduino Mega 2560 & Genuino


Mega 2560
× 1
NECESSARY TOOLS AND MACHINES
siccors

glue gun

tape

cutter knife

Ruller
APPS AND ONLINE SERVICES
1Sheeld iOS/Android App

ABOUT THIS PROJECT

I have been always fascinated by home automation devices and ever


wanted to get one of these security home camera, home temperature
monitor or even lights and air conditioner.
Even more, I dreamed of remotely control things in my home from outside
by using my phone. That takes me to create my own customized home
automation project that integrates IoT technology, into only one device...
an IoT home automation device!
So, let's get started with the idea...
Idea
The device is placed near the home door and is always connected to the
internet via my wifi router. And you can monitor your home environment
and control things by using just an app on your smartphone, called IoT
MQTT Panel.
The device has 3 sensors to monitor:
Door lock status using ultrasonic sensor
Temperature
Gas level
And allows you to control 3 things:
How It Works
Once you are outside home you can monitor your home light and control it
from the app by using a relay.
Also, you can monitor gas level inside your home with the gas sensor and
once it gets a dangerous level, an email will be sent to you automatically
from the device so you can take a quick action upon it and also the alarm
buzzer will be turned on and will stay alarming until someone notice it and
press it down.
And even take multiple pictures from different angles and they will be sent
to your email.
And when you are about to leave the office back to your home then you
can cool things by checking the home temperature and turn on the AC
with an auto-optimization mode.
This is done by using an IR sensor directed to the AC and the auto-
optimization mode will increase the AC temperature set point
automatically each 2 minutes for 2 times so that once you get arrived your
home is cooled nicely, not frozen!
Once you arrive home and open the door, the ultrasonic sensor will detect
your door movement and the device will tell you (with a text-to-speech) to
enter your pre-saved fingerprint so that the device knows that you are an
authorized person.
What if he wasn't an authorized one? Then the device will wait for 30
seconds and if the fingerprint hasn't been entered and matched, then it will
take a photo of that stranger and send it back to the owner's email.
In addition, once you press the speak button on your app, the device will
activate the voice-commands and listen to what you want like playing
music or turning lights on/off. Here, you can get relaxed reading your
favourite book and listening to your favorite music after a heavy working
day!
How to Make It
I am going to use Arduino with the IoT shield existed in
1Sheeld. 1Sheeld is basically an Arduino shield that collects 40+ shields
into only one shield!
Just a perfect and cheap board that empowers me to use the required
shields in this project:
IoT Shield for making the communication with the CloudMQTT online
server.
FingerPrint Scanner Shield to authorize the home entrance.
Buzzer Shield to act like an alarm for the high gas level.
Camera Shield to take photos of inside home.
Email Shield to get emails of photos taken by the phone's camera and gas
alet's emails.
Music Player Shield for playing music from phone.
Terminal Shield acts like a serial monitor "for debugging only."
Text-to-Speech Shield to say what I want. It acts like my own voice
assistance ")
Voice Recognition Shield which is the way I order the device to do what I
want orally.
And going to use 2 phones:
An iPhone to be connected with the 1Sheeld so that Arduino can connect
to the internet (and to the IoT online server, indeed) through the IoT shield
in the iPhone's 1Sheeld app.
An Android phone to use it as my personal phone that has the IoT MQTT
Panel App. And these of course in addition to the listed components and
fabrication materials.
So, I will go with you step by step to build this project from scratch but
please be patient since there is quite steps, components and coding here.
Before You Start Building It
I recommend you go for this 1Sheeld getting started tutorial to get familiar
with 1Sheeld.
Also, check this simple IoT tutorial with Arduino+1Sheeld to get familiar
with the IoT shield of 1Sheeld and how to setup the IoT MQTT Panel App
and the cloud MQTT server.
Step 1: Prepare the Materials and Cut the Box Faces
First, get the cardboard foam material and cut it into the below described
dimensions so you get 6 faces of the box.
Don't forget to make the holes for the components like ultrasonic, gas
sensor, etc.
Finally, you should get the box faces ready like that:
Note: the size of the 3D parts and the servo motor arm is up to you
according to your servo motor size and your iPhone. But in general, you
can use any alike plastic/wood pieces around you. Just make it easy for
yourself :)
Step 2: Build the Box
Now comes the assembly part where you glue the 5 faces of the box using
the glue gun.
And the 6th face which is the box's door you should install it with a tape
from its bottom side to act like a door to be able to open and close it
freely, like this:
Note: the box door is fixed to its closing position by using 2 small magnets
placed on the box door and 2 metal pieces placed on the correct faced
closing place.
Step 3: Connect the Components
You better start with plugging the 1Sheeld over the Arduino and install it
inside the box.
You should do it without messing things up inside the box by:
1 - Connect the jumper wires to the components: DHT sensor, ultrasonic,
servo, LEDs, buttons, etc.
2 - Glue each component to its hole over its place in the box using the glue
gun.
3 - Connect the other jumper wires terminal to the Arduino or power.
Step 4: Box Polishing
I have designed a sticker profile to cover the box so that it gets a visual
polish. The sticker is divided into 6 faces, indeed where you can download
them from here. Or you can use your own customized sticker.
After all, it will look like this:
Step 5: Adjust Box to the Wall
Then it's time to adjust the device near your home door with a helping 3D
printed 4 parts (2 over the box itself and 2 over the wall). You will find the
(.gcode) for it in the CAD part of the project so that your can print them
directly with the 3S printer.
Finally, connect the 2 relay output wires to the wall light switch.
And tape the IR to be pointed to face your air conditioner.
Step 6: IR Code for the Air Conditioner remote
Before uploading the code to your Arduino mega you should edit this part
which contains the Air Conditioner IR remote codes to your own in-home
Air Conditioner IR code:
// AC on/off at temp 23
unsigned int power[] = {4712, 2580, 384, 376, 380, 952, 380, 976, 356,
396, 360, 976, 356, 376, 380, 396, 356, 396, 360, 396, 356, 976, 356, 400,
356, 396, 356, 400, 356, 976, 356, 396, 360, 396, 356, 396, 360, 396, 356,
976, 356, 400, 356, 396, 356, 400, 356, 976, 356, 376, 380, 396, 356, 400,
356, 396, 356, 976, 360, 396, 356, 396, 360, 396, 356, 400, 356, 396, 356,
400, 356, 396, 356, 400, 356, 976, 356, 396, 360, 396, 356, 396, 360, 976,
356, 396, 356, 400, 356, 396, 360, 972, 360, 396, 360, 396, 356, 396, 356,
976, 360, 972, 360, 396, 356, 400, 356, 396, 356, 976, 356, 400, 356, 396,
360, 396, 356, 396, 360, 396, 356, 976, 360, 972, 360, 976, 356, 396, 360,
956, 356, 20116, 4676, 6568, 9276, 5012, 384, 396, 356, 396, 360, 396,
356, 400, 356, 396, 360, 396, 356, 396, 356, 400, 356, 396, 360, 396, 356,
396, 360, 396, 356, 976, 356, 976, 360, 396, 356, 396, 360, 396, 356, 396,
360, 396, 356, 396, 360, 396, 356, 400, 356, 976, 356, 396, 356, 400, 356,
396, 360, 396, 356, 396, 360, 396, 356, 400, 356, 396, 356, 396, 360, 396,
356, 400, 356, 396, 356, 400, 356, 396, 360, 396, 356, 396, 356, 400, 356,
396, 360, 396, 356, 400, 356, 396, 356, 396, 360, 396, 360, 396, 356, 396,
356, 400, 356, 396, 356, 400, 356, 396, 360, 396, 356, 396, 360, 396, 356,
396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 976, 356, 976, 356, 976,
356, 380, 360, 20116, 4672};
// AC temp+ from 23 to 24
unsigned int temp24[] = {4716, 2604, 360, 396, 356, 976, 356, 976, 360,
396, 356, 976, 356, 400, 356, 396, 356, 400, 356, 396, 356, 976, 360, 396,
356, 396, 360, 396, 356, 976, 360, 396, 356, 396, 360, 972, 360, 396, 356,
980, 352, 400, 356, 396, 360, 396, 356, 396, 360, 396, 356, 976, 356, 400,
356, 396, 356, 976, 360, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356,
400, 356, 396, 356, 400, 356, 976, 356, 396, 360, 396, 356, 400, 356, 976,
356, 396, 360, 396, 356, 396, 360, 976, 356, 396, 356, 400, 356, 396, 360,
396, 356, 396, 356, 976, 360, 396, 356, 400, 356, 976, 356, 396, 360, 396,
356, 396, 360, 396, 356, 396, 360, 396, 356, 400, 356, 976, 356, 396, 356,
380, 360, 20104, 4684, 6596, 9276, 5012, 356, 396, 360, 396, 356, 396,
360, 396, 356, 400, 356, 396, 356, 400, 356, 400, 356, 396, 356, 396, 356,
400, 356, 396, 360, 976, 356, 976, 356, 396, 360, 396, 356, 396, 360, 396,
356, 396, 360, 396, 356, 400, 356, 396, 356, 976, 356, 400, 356, 396, 356,
400, 356, 396, 360, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356, 400,
356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356,
400, 356, 400, 356, 396, 356, 400, 352, 400, 356, 400, 356, 396, 356, 400,
356, 396, 356, 400, 356, 396, 356, 400, 356, 400, 352, 400, 356, 400, 352,
400, 356, 400, 356, 396, 356, 400, 352, 400, 356, 980, 352, 980, 352, 980,
356, 380, 356, 20104, 4684};
// AC temp+ from 24 to 25
unsigned int temp25[] = {4716, 2604, 356, 400, 356, 976, 356, 976, 360,
396, 356, 976, 356, 396, 360, 396, 356, 400, 356, 396, 356, 976, 360, 396,
356, 396, 360, 396, 356, 976, 356, 400, 356, 396, 356, 400, 356, 396, 356,
976, 360, 396, 356, 396, 360, 396, 356, 976, 360, 396, 356, 396, 360, 396,
356, 396, 360, 972, 360, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356,
400, 356, 396, 360, 396, 356, 976, 356, 400, 356, 396, 356, 400, 356, 976,
356, 396, 360, 396, 356, 396, 360, 976, 356, 396, 360, 396, 356, 396, 356,
976, 360, 396, 356, 976, 356, 400, 356, 396, 360, 972, 360, 396, 356, 396,
360, 396, 356, 396, 360, 396, 356, 400, 356, 976, 356, 396, 360, 976, 356,
380, 356, 20108, 4684, 6592, 9276, 5012, 356, 396, 360, 396, 360, 396,
356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 356, 400, 356,
396, 356, 396, 360, 976, 356, 976, 356, 396, 360, 396, 356, 396, 360, 396,
356, 400, 356, 396, 356, 400, 356, 396, 360, 976, 356, 396, 356, 396, 360,
396, 356, 400, 356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396,
356, 396, 360, 396, 356, 396, 360, 396, 356, 400, 356, 396, 356, 400, 356,
396, 356, 400, 356, 396, 356, 400, 356, 396, 360, 396, 356, 396, 360, 396,
356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 360, 396, 356,
396, 356, 400, 356, 396, 356, 400, 356, 396, 360, 972, 360, 976, 356, 976,
356, 380, 356, 20080, 4712};
So, you need to know the IR codes responsible for:
Turning your Air Conditioner on/off at a temperature of 23.
Increasing your Air Conditioner temperature from 23 to 24.
Increasing your Air Conditioner temperature from 24 to 25.
The last 2 codes are required for the Auto-Optimization mode.
For me, this was the most difficult part of the whole code since all IR
remote libraries on the internet for Arduino aren't compatible with long
range of the codes generated by the Air Conditioner IR remotes since
these remotes generates IR codes with much more number of complex bits
that popular Arduino IR remote libraries can't recognize.
After a long search and trying combinations of codes I finally got it
working! You just need to make these connections between the Arduino
and an IR receiver:
Connections:
IR Receiver Arduino
V+ -> +5v
GND -> GND
Signal Out -> Digital Pin 2

Then, upload this code to your Arduino:


/*
Author: AnalysIR
Revision: 1.0
This code is provided to overcome an issue with Arduino IR libraries
It allows you to capture raw timings for signals longer than 255 marks &
spaces.
Typical use case is for long Air conditioner signals.
You can use the output to plug back into IRremote, to resend the signal.
This Software was written by AnalysIR.
Usage: Free to use, subject to conditions posted on blog below.
Please credit AnalysIR and provide a link to our website/blog, where
possible.
Copyright AnalysIR 2014
Please refer to the blog posting for conditions associated with use.
http://www.analysir.com/blog/2014/03/19/air-conditioners-problems-
recording-long-infrared-remote-control-signals-arduino/
Connections:
IR Receiver Arduino
V+ -> +5v
GND -> GND
Signal Out -> Digital Pin 2
(If using a 3V Arduino, you may connect V+ to +3V)
*/
#define LEDPIN 13
//you may increase this value on Arduinos with greater than 2k SRAM
#define maxLen 300
volatile unsigned int irBuffer[maxLen]; //stores timings - volatile because
changed by ISR
volatile unsigned int x = 0; //Pointer thru irBuffer - volatile because
changed by ISR
void setup() {
Serial.begin(115200); //change BAUD rate as required
attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);//set up ISR for
receiving IR signal
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(F("Press the button on the remote now - once only"));
delay(5000); // pause 5 secs
if (x) { //if a signal is captured
digitalWrite(LEDPIN, HIGH);//visual indicator that signal received
Serial.println();
Serial.print(F("Raw: (")); //dump raw header format - for library
Serial.print((x - 1));
Serial.print(F(") "));
detachInterrupt(0);//stop interrupts & capture until finshed here
for (int i = 1; i < x; i++) { //now dump the times
if (!(i & 0x1)) Serial.print(F("-"));
Serial.print(irBuffer[i] - irBuffer[i - 1]);
Serial.print(F(", "));
}
x = 0;
Serial.println();
Serial.println();
digitalWrite(LEDPIN, LOW);//end of visual indicator, for this time
attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);//re-enable ISR
for receiving IR signal
}
}
void rxIR_Interrupt_Handler() {
if (x > maxLen) return; //ignore if irBuffer is already full
irBuffer[x++] = micros(); //just continually record the time-stamp of
signal transitions
}
And open the serial monitor and press the on/off key from the IR remote
towards the IR receiver. You will get something like this on the screen:
Copy and paste the code you got in a text file. Code will be something like
this:
Raw: (267) 4644, -2604, 384, -416, 312, -1020, 316, -1016, 316, -440,
312, -1020, 312, -440, 312, -444, 312, -440, 312, -444, 312, -1016, 316,
-440, 312, -440, 316, -1016, 316, -440, 312, -444, 312, -440, 312, -444,
312, -1016, 316, -1016, 316, -440, 316, -1016, 320, -436, 312, -1016, 316,
-440, 316, -1016, 316, -440, 312, -440, 316, -440, 312, -440, 312, -440,
316, -440, 312, -440, 316, -440, 312, -440, 316, -440, 312, -440, 316,
-1016, 316, -440, 312, -440, 316, -440, 312, -440, 316, -440, 312, -440,
316, -436, 316, -1016, 316, -440, 316, -436, 316, -440, 316, -436, 316,
-440, 316, -1016, 316, -436, 316, -440, 316, -1016, 316, -436, 316, -440,
316, -436, 316, -440, 316, -436, 316, -1016, 316, -440, 312, -1020, 316,
-1016, 316, -420, 316, -20132, 4648, -6592, 9272, -5008, 384, -412, 316,
-440, 312, -440, 316, -436, 316, -440, 316, -436, 316, -440, 312, -440,
316, -440, 312, -440, 316, -440, 312, -440, 316, -440, 312, -440, 316,
-436, 316, -440, 316, -436, 316, -440, 316, -436, 316, -440, 312, -440,
316, -440, 312, -1020, 312, -440, 312, -444, 312, -440, 312, -444, 312,
-440, 312, -444, 312, -440, 312, -440, 316, -440, 312, -440, 316, -440,
312, -440, 312, -444, 312, -440, 316, -440, 312, -440, 312, -444, 312,
-440, 312, -440, 316, -440, 312, -440, 316, -440, 312, -440, 312, -444,
312, -440, 312, -444, 312, -440, 312, -444, 312, -440, 312, -440, 316,
-440, 312, -440, 316, -440, 312, -440, 316, -440, 312, -440, 316, -440,
312, -440, 312, -444, 312, -1016, 316, -424, 312, -20136, 4648,
If you noticed, the IR code for on/off switch has negative numbers. Many
of them, actually. Here, you must remove all these (-) signs and copy the
whole code with all numbers are positive to your project code.
Going to do all this manually! What's the hill!! Surely not, however, I did
it manually to test a new code I have made to take the IR remote code with
its negative numbers, removes all negative signs (-) and generates the
required clean IR code for you. All automatically! Yeah, here is it:
// ir received array
int irArray[] = {4716, -2604, 360, -396, 356, -976, 356, -976, 360, -396,
356, -976, 356, -400, 356, -396, 356, -400, 356, -396, 356, -976, 360,
-396, 356, -396, 360, -396, 356, -976, 360, -396, 356, -396, 360, -972,
360, -396, 356, -980, 352, -400, 356, -396, 360, -396, 356, -396, 360,
-396, 356, -976, 356, -400, 356, -396, 356, -976, 360, -396, 356, -400,
356, -396, 356, -400, 356, -396, 356, -400, 356, -396, 356, -400, 356,
-976, 356, -396, 360, -396, 356, -400, 356, -976, 356, -396, 360, -396,
356, -396, 360, -976, 356, -396, 356, -400, 356, -396, 360, -396, 356,
-396, 356, -976, 360, -396, 356, -400, 356, -976, 356, -396, 360, -396,
356, -396, 360, -396, 356, -396, 360, -396, 356, -400, 356, -976, 356,
-396, 356, -380, 360, -20104, 4684, -6596, 9276, -5012, 356, -396, 360,
-396, 356, -396, 360, -396, 356, -400, 356, -396, 356, -400, 356, -400,
356, -396, 356, -396, 356, -400, 356, -396, 360, -976, 356, -976, 356,
-396, 360, -396, 356, -396, 360, -396, 356, -396, 360, -396, 356, -400,
356, -396, 356, -976, 356, -400, 356, -396, 356, -400, 356, -396, 360,
-396, 356, -400, 356, -396, 356, -400, 356, -396, 356, -400, 356, -396,
356, -400, 356, -396, 356, -400, 356, -396, 356, -400, 356, -396, 356,
-400, 356, -400, 356, -396, 356, -400, 352, -400, 356, -400, 356, -396,
356, -400, 356, -396, 356, -400, 356, -396, 356, -400, 356, -400, 352,
-400, 356, -400, 352, -400, 356, -400, 356, -396, 356, -400, 352, -400,
356, -980, 352, -980, 352, -980, 356, -380, 356, -20104, 4684};
signed int irArraySize= sizeof(irArray) / sizeof(irArray[0]);
int i;
void setup() {
Serial.begin(9600);
delay(2000);
Serial.println("Wait .. I will convert your signed IR array now ...");
delay(1000);
Serial.println("");
/* print the old signed array */
Serial.println("Your original IR array with negative numbers:");
Serial.print("{");
for(i=0; i<irArraySize; i++)
{
Serial.print(irArray[i]);
Serial.print(", ");
}
Serial.print("}");
Serial.println("");
Serial.println("");
/* remove '-' sign from the original array and over right elements */
for(i=0; i<irArraySize; i++)
{
if(irArray[i] < 0 )
{
irArray[i] = irArray[i] * ( (signed int)(-1) );
}
}
/* print the new unsigned array */
Serial.println("Your new all positive numbers IR array:");
Serial.print("{");
for(i=0; i<irArraySize; i++)
{
Serial.print(irArray[i]);
Serial.print(", ");
}
Serial.print("}");
Serial.println("");
Serial.println("");
Serial.println("All finished .. ready to be copied");
}
void loop() {
// put your main code here, to run repeatedly:
}
Just replace the (irArray[]) content with the code you got which contains
the negative (-) numbers and upload the code to the Arduino and you will
get your new positive numbers IR code ready to be copied to the project
code.
And repeat that with the temp (+) button when Air Conditioner is turned
on at 23 c and temp (+) button again when Air Conditioner is on at 24 c.
Finally, you will get 3 IR array codes for the 3 positions we mentioned
before:
Turning your Air Conditioner on/off at a temperature of 23.
Increasing your Air Conditioner temperature from 23 to 24.
Increasing your Air Conditioner temperature from 24 to 25.
Copy these arrays to replace them with those in the project code.
Step 7: Arduino Code
Connect the Arduino via your PC using Arduino USB cable.
Switch the 1Sheeld power to operate on 5v (Not the 3.3v):
1Sheeld have 2 modes: Uploading mode and Operating mode. You can
switch between them using the switch close to the Digital pins and is
called “UART SWITCH” on 1Sheeld and “SERIAL SWITCH” on
1Sheeld+.
Firstly, you slide the switch towards the “SWITCH” notation which turns
the 1Sheeld board into the Uploading mode to let you upload the Arduino
code.
Note: You have to add these attached code files [dht.cpp - dht.h -
TimerOne.cpp - TimerOne.h] in the same folder of the Arduino code file
as they are libraries I used in the Arduino code.
Secondly, after you finish uploading the code, slide the switch towards the
“UART” notation (or “SERIAL” at 1Sheeld+ board) which turns
the 1Sheeld board into the Operating mode to communicate with your
smartphone 1Sheeld app.
Finally, open the 1Sheeld app and connect it to the 1Sheeld board via
Bluetooth.
Step 8: Configuring the App
Now move on to download the IoT MQTT Panel App. You need to
configure the app with MQTT server instance credentials you have gotten
from the CloudMQTT online server.
I have made it with the help of this IoT tutorial which will show you how
to add just the light button widget and use it with the app:
And this IoT Temperature sensor tutorial which will show you how to add
a sensor reading widget and use it with the app.
After that, you will be able to add all other widgets easily like AC button,
Auto-Optimization button, Speak, Camera Capture button, Camera Servo
slider, gas level reading widget, Door Status widget. You should finish it
with a full panel like this:
Release the IoT Home Automation Monster!
Once finished all the steps, insert the batteries:
Then turn the device on from the left side switch:
And connect your iPhone with the 1Sheeld then press the reset button on
the device left side.
Then open the IoT MQTT Panel App and you are ready to go and control
and monitor your home anytime, anywhere with just your own
smartphone!
SCHEMATICS
CODE
/*
Arduino IoT Quality Project using IoT Shield from 1Sheeld

OPTIONAL:
To reduce the library compiled size and limit its memory usage, you
can specify which shields you want to include in your sketch by
defining CUSTOM_SETTINGS and the shields respective INCLUDE_ define.
*/

/* Include all required shields */


#define CUSTOM_SETTINGS
#define INCLUDE_IOT_SHIELD
#define INCLUDE_TERMINAL_SHIELD
#define INCLUDE_EMAIL_SHIELD
#define INCLUDE_CAMERA_SHIELD
#define INCLUDE_BUZZER_SHIELD
#define INCLUDE_FINGERPRINT_SCANNER_SHIELD
#define INCLUDE_TEXT_TO_SPEECH_SHIELD
#define INCLUDE_MUSIC_PLAYER_SHIELD
#define INCLUDE_VOICE_RECOGNIZER_SHIELD

/* Define the devices signal pin */


#define camServoPin 3
#define light_pin 8
#define gas_switch_pin 21
#define gas_switch_led_pin 11
#define test_led 7
#define trigPin 4
#define echoPin 5
#define ir_led 9

/* Include 1Sheeld library. */


#include <OneSheeld.h>

/* Include IR library */
#include <IRremote.h>

/* Include servo motor library */


#include <Servo.h>

/* Include the dht11 sensor library */


#include "DHT.h"

/* Define the sensors signal pins */


#define TEMP_PIN A0
#define GAS_PIN A1

/* Initia servo objects */


Servo CamServo;

/* Initia IR object */
IRsend irsend;

/* Crea an instance of the dht11 */


dht DHT;

/* door status variables to prevent multiple publication */


bool published_door_status_closed = false;
bool published_door_status_opened = false;

/* Variable to save the measured distance from ultrasonic */


int distance;

/* 38kHz carrier frequency for the NEC protocol */


int khz = 38;

// AC on/off at mp 23
unsigned int power[] = {4712, 2580, 384, 376, 380, 952, 380, 976, 356, 396, 360, 976, 356,
376, 380, 396, 356, 396, 360, 396, 356, 976, 356, 400, 356, 396, 356, 400, 356, 976, 356,
396, 360, 396, 356, 396, 360, 396, 356, 976, 356, 400, 356, 396, 356, 400, 356, 976, 356,
376, 380, 396, 356, 400, 356, 396, 356, 976, 360, 396, 356, 396, 360, 396, 356, 400, 356,
396, 356, 400, 356, 396, 356, 400, 356, 976, 356, 396, 360, 396, 356, 396, 360, 976, 356,
396, 356, 400, 356, 396, 360, 972, 360, 396, 360, 396, 356, 396, 356, 976, 360, 972, 360,
396, 356, 400, 356, 396, 356, 976, 356, 400, 356, 396, 360, 396, 356, 396, 360, 396, 356,
976, 360, 972, 360, 976, 356, 396, 360, 956, 356, 20116, 4676, 6568, 9276, 5012, 384, 396,
356, 396, 360, 396, 356, 400, 356, 396, 360, 396, 356, 396, 356, 400, 356, 396, 360, 396,
356, 396, 360, 396, 356, 976, 356, 976, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396,
356, 396, 360, 396, 356, 400, 356, 976, 356, 396, 356, 400, 356, 396, 360, 396, 356, 396,
360, 396, 356, 400, 356, 396, 356, 396, 360, 396, 356, 400, 356, 396, 356, 400, 356, 396,
360, 396, 356, 396, 356, 400, 356, 396, 360, 396, 356, 400, 356, 396, 356, 396, 360, 396,
360, 396, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 360, 396, 356, 396, 360, 396,
356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 976, 356, 976, 356, 976, 356, 380,
360, 20116, 4672};

// AC mp+ from 23 to 24
unsigned int temp24[] = {4716, 2604, 360, 396, 356, 976, 356, 976, 360, 396, 356, 976,
356, 400, 356, 396, 356, 400, 356, 396, 356, 976, 360, 396, 356, 396, 360, 396, 356, 976,
360, 396, 356, 396, 360, 972, 360, 396, 356, 980, 352, 400, 356, 396, 360, 396, 356, 396,
360, 396, 356, 976, 356, 400, 356, 396, 356, 976, 360, 396, 356, 400, 356, 396, 356, 400,
356, 396, 356, 400, 356, 396, 356, 400, 356, 976, 356, 396, 360, 396, 356, 400, 356, 976,
356, 396, 360, 396, 356, 396, 360, 976, 356, 396, 356, 400, 356, 396, 360, 396, 356, 396,
356, 976, 360, 396, 356, 400, 356, 976, 356, 396, 360, 396, 356, 396, 360, 396, 356, 396,
360, 396, 356, 400, 356, 976, 356, 396, 356, 380, 360, 20104, 4684, 6596, 9276, 5012, 356,
396, 360, 396, 356, 396, 360, 396, 356, 400, 356, 396, 356, 400, 356, 400, 356, 396, 356,
396, 356, 400, 356, 396, 360, 976, 356, 976, 356, 396, 360, 396, 356, 396, 360, 396, 356,
396, 360, 396, 356, 400, 356, 396, 356, 976, 356, 400, 356, 396, 356, 400, 356, 396, 360,
396, 356, 400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356,
400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 400, 356, 396, 356, 400, 352, 400, 356,
400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 400, 352, 400, 356,
400, 352, 400, 356, 400, 356, 396, 356, 400, 352, 400, 356, 980, 352, 980, 352, 980, 356,
380, 356, 20104, 4684};

// AC mp+ from 24 to 25
unsigned int temp25[] = {4716, 2604, 356, 400, 356, 976, 356, 976, 360, 396, 356, 976,
356, 396, 360, 396, 356, 400, 356, 396, 356, 976, 360, 396, 356, 396, 360, 396, 356, 976,
356, 400, 356, 396, 356, 400, 356, 396, 356, 976, 360, 396, 356, 396, 360, 396, 356, 976,
360, 396, 356, 396, 360, 396, 356, 396, 360, 972, 360, 396, 356, 400, 356, 396, 356, 400,
356, 396, 356, 400, 356, 396, 360, 396, 356, 976, 356, 400, 356, 396, 356, 400, 356, 976,
356, 396, 360, 396, 356, 396, 360, 976, 356, 396, 360, 396, 356, 396, 356, 976, 360, 396,
356, 976, 356, 400, 356, 396, 360, 972, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396,
356, 400, 356, 976, 356, 396, 360, 976, 356, 380, 356, 20108, 4684, 6592, 9276, 5012, 356,
396, 360, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 356,
400, 356, 396, 356, 396, 360, 976, 356, 976, 356, 396, 360, 396, 356, 396, 360, 396, 356,
400, 356, 396, 356, 400, 356, 396, 360, 976, 356, 396, 356, 396, 360, 396, 356, 400, 356,
396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360,
396, 356, 400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 360,
396, 356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 356, 396, 360, 396, 360,
396, 356, 396, 356, 400, 356, 396, 356, 400, 356, 396, 360, 972, 360, 976, 356, 976, 356,
380, 356, 20080, 4712};

/* auto optimization variable */


bool isAutoOptimize = false;

/* temp24 and temp25 checking variables */


bool temp24_isSent = false;
bool temp25_isSent = false;

/* sensor variabes */
int temp;
int gas_degree;
bool gas_HighLevelWarning = false;
bool gas_emailSent = false;
bool alarm_isPressed = false;
bool interruptPin_isPressed = false;
/* required variables for the publishing function */
char tempChar[4];
char gas_degree_char[4];

/* time relad variables */


bool isAuthorized = true;
unsigned long start_time;
unsigned long time_passed;

unsigned long ac_start_time;


unsigned long ac_time_passed;

/* broker instance security details */


const char * host_name = "m12.cloudmqtt.com";
const char * user = "azlckshz";
const char * password = "aoRcZqKQV0Kf";
const int port = 11911;

/* The topics*/
const char * ultrasonic = "ultrasonic";
const char * cam_dir = "cam/direction";
const char * cam_cap = "cam/capture";
const char * light = "light";
const char * temperature = "temp";
const char * gas = "gas";
const char * speak = "speak";
const char * ac = "ac";
const char * ac_auto = "auto";

byte interruptPin = gas_switch_pin;


void setup()
{
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), interruptPin_isr, FALLING);
// pinMode(gas_switch_pin , INPUT_PULLUP);
pinMode(gas_switch_led_pin , OUTPUT);
pinMode(light_pin , OUTPUT);
pinMode(test_led , OUTPUT);
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
/* Configure Arduino to use this pin as the servo signal pin */
CamServo.attach(camServoPin);

/* Start communication. */
OneSheeld.begin();
/* Disconnect from broker. */
IOT.disconnect();

/* Reset all connection variables to default */


IOT.resetConnectionParametersToDefaults();

/* Connect to mosquitto's public broker. */


IOT.connect(host_name, user, password, port);

/* Subscribe to new messages. */


IOT.setOnNewMessage(&newMessage);

/* Subscribe to connnection status callback. */


IOT.setOnConnectionStatusChange(&connectionStatus);

/* Subscribe to error callback. */


IOT.setOnError(&error);

/* Some time for app to connect. */


delay(3000);

/* Subscribions to topics */
IOT.subscribe(ultrasonic);
IOT.subscribe(cam_dir);
IOT.subscribe(cam_cap);
IOT.subscribe(light);
IOT.subscribe(speak);
IOT.subscribe(ac);
IOT.subscribe(ac_auto);

/* publish ready once light is connecd */


IOT.publish("status", "ready", QOS_0);

/* Start servo at the 90 degree angle */


CamServo.write(90);

void loop()
{
/************************************************* Ultrasonic Sensor
*****************************************************/
/* Get the current distance from the ultrasonic */
distance = getUltrasonicDistance();
//terrminal.println("");
//Terminal.print("distance:");
//Terminal.println(distance);
if ( (distance < 30) && (distance > 0) && (isAuthorized == true) )
{
isAuthorized = false;
start_time = millis();
TextToSpeech.say("please enter your fingerprint");
OneSheeld.delay(1400);

if(published_door_status_opened == false)
{
/* Publish door status as opened */
IOT.publish(ultrasonic, "your door is opened", QOS_0);

/* ensure publisjing one time only */


published_door_status_opened = true;
}
}
else
{
if(published_door_status_closed == false)
{
/* Publish door status as opened */
IOT.publish(ultrasonic, "your door is closed", QOS_0);

/* ensure publisjing one time only */


published_door_status_closed = true;
}
}
/************************************************* fingerprint security timer
*****************************************************/
if ( isAuthorized == false )
{
time_passed = (unsigned long) (millis() - start_time);
if ( FingerprintScanner.isNewFingerScanned() && FingerprintScanner.isVerified())
{
isAuthorized = true;
TextToSpeech.say("fingerprint matched");
OneSheeld.delay(1100);
TextToSpeech.say("welcome home");
OneSheeld.delay(1200);

/* allow publishing again */


published_door_status_closed = false;
published_door_status_opened = false;
}
if ( time_passed >= 30000 )
{
isAuthorized = true;
TextToSpeech.say("you are not authorized");
OneSheeld.delay(1500);

/* 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]", "Security Alert!", "Hi, A stranger
has entered your home and I got a photo of him. Check it out", 1);

/* delay for the email */


OneSheeld.delay(3000);
}
}

/************************************************* air conditioner timer


*****************************************************/
ac_time_passed = (unsigned long) (millis() - ac_start_time);
if( isAutoOptimize )
{
/* increase the AC temperature from 23 to 24C if the time passed since on is >= 2sec */
if ( ac_time_passed >= (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 ; start_angle++ )
{
CamServo.write(start_angle);
delay(25);
}
}
else if ( 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

Microchip ATtiny85

× 1

Arduino UNO & Genuino UNO

× 1

LED (generic)

× 1

Jumper wires (generic)

× 1

HC-05 Bluetooth Module

× 1
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 HC-
05 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 <SoftwareSerial.h> //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

× 1

Adafruit LIS3DH Accelerometer


× 1

AD5206 10K digital potentiometer


× 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 <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
// 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 << lis.getRange());
Serial.println("G");
//initialize the pots at reasonable values
digitalPotWrite(pitch, 60);
digitalPotWrite(throttle, 51);
}

void loop() {
lis.read();
accelValue = lis.z;
//values must be determined empirically:
accelValue = constrain(accelValue, -16383, 16383);
rollValue = map(accelValue, -16383, 16383, 51, 204);
//hand tilt controls roll
digitalPotWrite(roll, rollValue);

pitchValue = digitalRead(pitchPin);
throttleValue = digitalRead(throtPin);

//"throttle" button is connected to the "arm" switch of transmitter and state


//is read by Arduino. Pressing the button arms the drone and the Arduino
can
//then gradually raise the throttle
if (!throttleValue) {
if (flag == 0) {
flag = 1;//throttle button is pressed
for (int level = 51;level<maxThrottle;level++) {
digitalPotWrite(throttle, level);
delay(2);
}
} else {
digitalPotWrite(throttle,maxThrottle);
}
} else {
if (flag == 1) {
flag = 0;
for (int level = maxThrottle;level<52;level--) {
digitalPotWrite(throttle, level);
delay(2);
}
} else {
digitalPotWrite(throttle,51);
}
}

//the pitch button is a single bit, so whened pressed the pitch is


//gradually raised, and when not pressed the pitch is gradually
//lowered. So just forwards and backwards, good luck!
//values must be determined empirically:
if(pitchValue) {
if(pitchFlag==0){
pitchFlag=1;
for (int level = 94; level<160; level++){
digitalPotWrite(pitch, 255-level);
delay(2);
}
} else {
digitalPotWrite(pitch, 94);
}
} else{
if(pitchFlag==1) {
pitchFlag=0;
for (int level = 94; level<160; level++){
digitalPotWrite(pitch, level);
delay(2);
}
} else {
digitalPotWrite(pitch, 160);
}
}
}

void digitalPotWrite(int address, int value) {


// take the SS pin low to select the chip:
digitalWrite(slaveSelectPin, LOW);
// send in the address and value via SPI:
SPI.transfer(address);
SPI.transfer(value);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin, HIGH);
}
204) Arduino Mr. Big

COMPONENTS AND SUPPLIES


Arduino UNO & Genuino UNO

× 1

SparkFun Dual H-Bridge motor


drivers L298 × 1

HC-05 Bluetooth Module

× 1

Jumper wires (generic)

× 1

Geared DC Motor, 12 V

× 2

wheels 60cm
× 2

castor wheel
× 1
NECESSARY TOOLS AND MACHINES
Drill, Screwdriver
APPS AND ONLINE SERVICES
Blynk

Arduino IDE

ABOUT THIS PROJECT

Back at my home during my summer vacations, everyone in the house


asked me to bring their stuffs from the other rooms. It was ok if the stuff
was small or limited in number but most of the time it wasn't. So I thought
of designing a mobile unit that I could operate via my phone and let it do
the heavy lifting.
I had my writing table at my home and also I arranged some plywood
which used for the external framework. The whole structure itself weigh
about 3-4kgs but you can use something lighter for the external structure if
you want.
Both motors used have a torque of 3 kg-cm. You can use a more powerful
motor if u want if you have a motor driver for it.
I have used a L298N motor driver for these project. I know it can operate
only for 3Amps current and both the motor will use more than that limit,
but the fact is it can whit stand up to 5Amps because manufacturers show
less value than actual. And worst case scenario in these case would be
thermal shutdown above 100 degree C.
I have used Blynk app for the purpose of controlling my robot. The sketch
for the same is given below. The robot as you know is controlled via
Bluetooth. You will get the necessary information on the official website
of Blynk you need. I have decided to controlled both the motor speed
separately but if you want you can control the speed through one
controller only. I have also added a button for forced left in the virtual pins
3 and 4. In the case if robot got stuck somewhere and it is needed to
change its direction immediately this commands can be used. But these
command puts a lot of pressure on the motor drive so better to save it for
emergency only. I have also used an LED button, it is a simple button to
know whether your Bluetooth is connected to your mobile device or not.
Just click that button, and if the light near 13th pin of Arduino Uno blinks
accordingly, then voila your mobile is connected via HC-05.
SCHEMATICS
CODE
#define BLYNK_PRINT Serial

#include <SoftwareSerial.h>
SoftwareSerial SwSerial(9, 10); // RX, TX
const int enb=6;
const int in4=12;
const int in3=11;
const int ena=3;
const int in2=5;
const int in1=4;
#include <BlynkSimpleSerialBLE.h>
#include <SoftwareSerial.h>
char auth[] = "5b4640909c9b4c818d9afdffc7a1ba08";

SoftwareSerial SerialBLE(9, 10); // RX, TX

// This function will be called every time Slider Widget


// in Blynk app writes values to the Virtual Pin 1

BLYNK_WRITE(V0)
{
int button=param.asInt();
if(button==1)
{
digitalWrite(in4,HIGH);
digitalWrite(in3,LOW);

digitalWrite(in1,HIGH);
digitalWrite(in2,LOW);
}
else if(button==0)
{
digitalWrite(in4,LOW);
digitalWrite(in3,HIGH);

digitalWrite(in1,LOW);
digitalWrite(in2,HIGH);
}
}
BLYNK_WRITE(V1)
{
int pinValue = param.asInt(); // assigning incoming value from pin V1 to a
variable

analogWrite(enb,pinValue);
}
BLYNK_WRITE(V2)
{
int pinValue = param.asInt(); // assigning incoming value from pin V1 to a
variable

analogWrite(ena,pinValue);
}

BLYNK_WRITE(V3)
{
int pinValue=param.asInt();
if(pinValue==1)
{
digitalWrite(in1,HIGH);
digitalWrite(in2,LOW);
digitalWrite(in4,LOW);
digitalWrite(in3,HIGH);
analogWrite(ena,255);
analogWrite(enb,255);
delay(500);
}
else
{
digitalWrite(in1,HIGH);
digitalWrite(in2,HIGH);
digitalWrite(in4,HIGH);
digitalWrite(in3,HIGH);
analogWrite(ena,0);
analogWrite(enb,0);
delay(200);
}
}
BLYNK_WRITE(V4)
{
int pinValue=param.asInt();
if(pinValue==1)
{
digitalWrite(in1,LOW);
digitalWrite(in2,HIGH);
digitalWrite(in4,HIGH);
digitalWrite(in3,LOW);
analogWrite(ena,255);
analogWrite(enb,255);
delay(500);
}
else
{
digitalWrite(in1,HIGH);
digitalWrite(in2,HIGH);
digitalWrite(in4,HIGH);
digitalWrite(in3,HIGH);
analogWrite(ena,0);
analogWrite(enb,0);
delay(200);
}
}

void setup()
{
// Debug console
Serial.begin(9600);

SerialBLE.begin(9600);
Blynk.begin(SerialBLE, auth);

Serial.println("Waiting for connections...");


pinMode(in3,OUTPUT);
pinMode(in4,OUTPUT);
pinMode(enb,OUTPUT);
pinMode(in2,OUTPUT);
pinMode(in1,OUTPUT);
pinMode(ena,OUTPUT);
}

void loop()
{
Blynk.run();
}

205) Arduino GoPRO Shutter


COMPONENTS AND SUPPLIES

Arduino MKR1000

× 1

LED (generic)

× 3

SparkFun Pushbutton switch


12mm
× 3

Breadboard (generic)

× 1

Jumper wires (generic)

× 1

Resistor 221 ohm

× 1
APPS AND ONLINE SERVICES
Arduino Web Editor

ABOUT THIS PROJECT


Arduino GoPRO libraries
This tutorial relies on the use of the Arduino GoPRO libray that can be
installed using the Arduino Library Manager.
This library allows the user to fully communicate with a GoPRO camera,
but we will use only two very basic functions:
Turn ON and OFF the camera;
Start or stop the capture;
How it Works
The libraries relies on the fact that a connection between the camera (in
AP mode) and the board exist.
The library has so the method GoPRO.begin(ssid, pass) to try a
connection. This function in fact returns true if the connection is
established false otherwise.
The sketch interacts with three buttons:
Connect/Disconnect (attached to A1);
Turn ON/OFF the camera (attached to A2);
Start/Stop Capture (attached to A3);
Pressing the buttons reflects to the status of the three LEDs in such a way:
Blue LED: when the connect button is pressed, the board tries to establish
a connection with the camera. If the connection is successful, the LED will
be turned ON. If pressed another time the connection will be stopped and
the LED is turned OFF;
Green LED:when the turn ON/OFF button is pressed, the board sends
the turnOn() command if the LED is OFF the turnOff() command
otherwise;
Red LED:when the Start/Stop Capture button is pressed, the board sends
the startCapture() command if the LED is OFF
the stopCapture() command otherwise;
NB: Every command is sent only if the connection between the board and
the camera is still active. This can be check using the
method checkConnection() that returns true if the connection is
active, false otherwise.
SCHEMATICS

CODE
/*

This example is free software; you can redistribute it and/or modify it


under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

This example 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 Lesser General Public License for more details.

*/

#include <GoPRO.h>

#define CONNECT_PRESSED 1

#define ON_PRESSED 2

#define CAPTURE_PRESSED 3

char ssid[] = "yourNetwork"; // your network SSID (name)

char pass[] = "yourPassword"; // your network password

const int buttonConnect = A1;

const int buttonOn = A2;

const int buttonCapture = A3;

const int connectLED = 3;

const int onLED = 4;

const int captureLED = 5;

bool onStatus = true;

bool captureStatus = false;

void setup() {
// put your setup code here, to run once:

pinMode(buttonConnect, INPUT_PULLUP);

pinMode(buttonOn, INPUT_PULLUP);

pinMode(buttonCapture, INPUT_PULLUP);

pinMode(connectLED, OUTPUT);

pinMode(onLED, OUTPUT);

pinMode(captureLED, OUTPUT);

digitalWrite(connectLED, LOW);

digitalWrite(onLED, HIGH);

digitalWrite(captureLED, LOW);

void loop() {

switch (isButtonPressed()) {

default: break;

case CONNECT_PRESSED:

if (!GoPRO.checkConnection()) {

if (GoPRO.begin(ssid, pass)) {
digitalWrite(connectLED, HIGH);

else {

digitalWrite(connectLED, LOW);

else {

digitalWrite(connectLED, HIGH);

break;

case ON_PRESSED:

if (GoPRO.checkConnection()) {

onStatus = !onStatus;

if (onStatus) {

if (GoPRO.turnOn())

digitalWrite(onLED, HIGH);

}
else {

if (GoPRO.turnOff())

digitalWrite(onLED, LOW);

break;

case CAPTURE_PRESSED:

if (GoPRO.checkConnection()) {

captureStatus = !captureStatus;

if (captureStatus) {

if (GoPRO.startCapture())

digitalWrite(captureLED, HIGH);

else {

if (GoPRO.stopCapture())

digitalWrite(captureLED, LOW);

}
}

break;

delay(100);

}
int isButtonPressed() {

if (digitalRead(buttonConnect) == LOW) return 1;

else if (digitalRead(buttonOn) == LOW) return 2;

else if (digitalRead(buttonCapture) == LOW) return 3;

else return 0;

}
206) Arduino What is Interrupts
COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

LED (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT


nterrupt is a signal emitted by hardware or software when a process or an
event needs immediate attention.
Interrupt is a signal emitted by hardware or software when a process or an
event needs immediate attention. It alerts the processor to a high priority
process requiring interruption of the current working process. In I/O
devices one of the bus control lines is dedicated for this purpose and is
called the Interrupt Service Routine (ISR).
Consider a case, while a car is running, Micro-controller is busy sensing
speed of the car, checking other sensors, controlling air conditioner
temperature etc. But suddenly an accident happened ! At that time
controller stops all the works and go to airbag activation section. So what
makes a sudden opening of air bag in seconds? An interrupt signal is used
here which has the highest priority of all.
There are software and Hardware interrupts :
Hardware Interrupts - These occur in response to an external event, like a
pin going high or low.
Software Interrupts - These occur in response to a software
instruction.Hardware Interrupts - These occur in response to an external
event, like a pin going high or low.
How Does It Work?
When the event or interrupt happens, the processor takes immediate
notice, saves its execution state, runs a small chunk of code (often called
the interrupt handler or interrupt service routine), and then returns back to
whatever it was doing before.
Let's try one simple interrupt using Arduino UNO.
In Arduino function called attachInterrupt() to do this task, its syntax looks
like
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)
digitalPinToInterrupt(pin):- Pin number of the interrupt, which tells the
microprocessor which pin to monitor. The pin depends on the
microcontroller being used.
ISR :- The location of code we want to execute if this interrupt is
triggered.
mode :- defines when the interrupt should be triggered. Four constants are
predefined as valid values:* LOW to trigger the interrupt whenever the pin
is low,* CHANGE to trigger the interrupt whenever the pin changes
value* RISING to trigger when the pin goes from low to high,* FALLING
for when the pin goes from high to low.

Interrupt pin : source: arduino.cc


Basic LED ON circuit using interrupt signal

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;
}
}
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

Alphanumeric LCD, 16 x 2

× 1

Fan kit 40mm


× 1

LED (generic)

× 5

Resistor 221 ohm

× 1

Single Turn Potentiometer- 10k


ohms
× 1
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.h>
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

Jumper wires (generic)

× 1

Arduino Nano R3

× 1

Adafruit OLED 0.96 LCD


× 1

Adafruit Waterproof DS18B20


Digital temperature sensor
× 1

Resistor 4.75k ohm

× 1
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 <SPI.h>
#include <Wire.h>
#include <OneWire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#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<40&&T_diff>=30 )
{
HeaterPWM=54;//full voltage;
voltage_perc=85;
}
else if(T_diff<30&&T_diff>=20 )
{
HeaterPWM=48; //60%
voltage_perc=75;
}
else if(T_diff<20&&T_diff>=10 )
{
HeaterPWM=38; //50%
voltage_perc=50;
}
else if(T_diff<10&&T_diff>=2 )
{
HeaterPWM=30; //30%
voltage_perc=30;
}
else if(T_diff<2 )
{
HeaterPWM=12; //0%
voltage_perc=0;
}
analogWrite(SugarPin,HeaterPWM);
}
void ReadTempSensor()
{
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;

if ( !ds.search(addr)) {
ds.reset_search();
delay(250);
return;
}
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
type_s = 1;
break;
case 0x28:
type_s = 0;
break;
case 0x22:
type_s = 0;
break;
default:
return;
}

ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end

delay(1000); // maybe 750ms is enough, maybe not


// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad

for ( i = 0; i < 9; i++) { // we need 9 bytes


data[i] = ds.read();
}

// Convert the data to actual temperature


// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
Temp=celsius;
fahrenheit = celsius * 1.8 + 32.0;
}
209) Arduino Switching ON/OF Aplliances Using IR Remote

COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

IR receiver (generic)
× 1

IR Remote Control
× 1

Adafruit RGB Backlight LCD -


16x2
× 1

Single Turn Potentiometer- 10k


ohms
× 1

Resistor 221 ohm

× 1

SPDT 5V Relay
× 2
APPS AND ONLINE SERVICES

Arduino IDE

ABOUT THIS PROJECT


Use an IR Remote to control the appliances (fan and light here).
Instructions :
Press the red power button to switch OFF/ON both things at once.
Press button 1 to switch ON the fan and press 2 to switch ON the
light.
Press button 1 again to switch off the fan and so for the light, too.
If you are making this project in real life, remember to power the relay
SPDT with 5V coil through a 5V source only, and for the best
performance of appliances, allow an external high power supply in the
COM terminal of the relay.
But make sure that the high voltage wires should not come in contact
with the low voltage Arduino and LCD circuitry as they work on 5V
and short circuiting in the the system may damage the Arduino and
other components.
Note : With different IR remotes, you should first check the codes of
each button of the remote you are using.
SCHEMATICS
CODE
#include <IRremote.h> //including infrared remote header file
#include <LiquidCrystal.h> //including LCD header file
#define code1 16582903 // code received from button 1
#define code2 16615543 // code received from button 2
#define code3 16580863 // code received from "power button"

LiquidCrystal lcd(12,10,7,6,5,4);

int RECV_PIN = 11; // the pin where you connect the output pin of IR
sensor
IRrecv irrecv(RECV_PIN);
decode_results results;

int app1 = 3; //fan pin


int app2 = 2; //bulb pin
int status[] = {0,0,0,0};
/* the initial state of appliances is OFF (zero)
the first zero must remain zero but you can
change the others to 1's if you want a certain
appliance to be ON when the board is powered */

void setup()
{
Serial.begin(9600);
lcd.begin(16,2); // Start the LCD
irrecv.enableIRIn(); // Start the IR receiver

pinMode(app1, OUTPUT);
pinMode(app2, OUTPUT);

lcd.setCursor(0,0);
lcd.print("Made by Naman"); // Made by Naman Chauhan
lcd.setCursor(0,1);
lcd.print("Chauhan");
delay(1500);
lcd.clear();
lcd.setCursor(3,0);
lcd.print("Arduino IR"); //Arduino IR Switch Board
lcd.setCursor(2,1);
lcd.print("Switch Board");
delay(1500);
lcd.clear();

lcd.setCursor(0,0);
lcd.print("(1) Fan : OFF"); //Showing intial status on LCD
lcd.setCursor(0,1);
lcd.print("(2) Bulb : OFF");

void loop()
{
if (irrecv.decode(&results)) {
unsigned int value = results.value;
switch(value) {

case code1:
if(status[1] == 1) { // if first app is ON then
digitalWrite(app1, LOW); // turn it off when button is pressed
status[1] = 0; // and set its state as off
lcd.setCursor(10,0); //printing status on LCD
lcd.print("OFF");
}

else { // else if first app is OFF then


digitalWrite(app1, HIGH); // turn it on when the button is pressed
status[1] = 1; // and set its state as ON
lcd.setCursor(10,0); //printing status on LCD
lcd.print("ON ");
}
break;

case code2:
if(status[2] == 1) {
digitalWrite(app2, LOW);
status[2] = 0;
lcd.setCursor(11,1); //printing status on LCD
lcd.print("OFF");
}

else {
digitalWrite(app2, HIGH);
status[2] = 1;
lcd.setCursor(11,1); //printing status on LCD
lcd.print("ON ");
}
break;

case code3:
if(status[1] == 1 && status[2] == 1) {
digitalWrite(app1, LOW);
status[1] = 0;
lcd.setCursor(10,0);
lcd.print("OFF");

digitalWrite(app2, LOW);
status[2] = 0;
lcd.setCursor(11,1);
lcd.print("OFF");
}

else {
digitalWrite(app1, HIGH);
status[1] = 1;
lcd.setCursor(10,0);
lcd.print("ON ");

digitalWrite(app2, HIGH);
status[2] = 1;
lcd.setCursor(11,1);
lcd.print("ON ");
}

}
Serial.println(value);
irrecv.resume(); // Receive the next value
}
}

210) DIY Solar Tracker Arduino Project


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Breadboard (generic)

× 1

Resistor 1k ohm
× 4

SG90 Micro-servo motor

× 2

Photo resistor

× 4

ABOUT THIS PROJECT


DIY Solar Tracker Arduino Project ITA
Hi everyone, in this article we are going to make a Solar Tracker
("Solar Tracker") using Arduino. A solar tracker is a mechanical-
automatic device that through sensors can understand the position of
the Sun that thanks to the motors you can follow it so as to store more
solar energy. Let's see how it builds !!
Needs:
To carry out this project we need the following materials:
• Arduino UNO;
• 4 220 Ω resistors;
• 4 photoresistors;
• 2 Servomotors;
• Breadboard;
• Solar Panel ;

SCHEMATICS
CODE
//Ingeimaks
#include <Servo.h>
//definiamo i servomotori orizzontale e verticale
Servo servohori;
int servoh = 0;
int servohLimitHigh = 160;
int servohLimitLow = 60;

Servo servoverti;
int servov = 0;
int servovLimitHigh = 160;
int servovLimitLow = 60;
//Pin fotoresistenze
int ldrtopl = 2; //top left
int ldrtopr = 1; //top right
int ldrbotl = 3; // bottom left
int ldrbotr = 0; // bottom right

void setup ()
{
servohori.attach(10);
servohori.write(60);
servoverti.attach(9);
servoverti.write(60);
Serial.begin(9600);
delay(500);

void loop()
{
servoh = servohori.read();
servov = servoverti.read();
//Valore Analogico delle fotoresistenza
int topl = analogRead(ldrtopl);
int topr = analogRead(ldrtopr);
int botl = analogRead(ldrbotl);
int botr = analogRead(ldrbotr);
// Calcoliamo una Media
int avgtop = (topl + topr) ; //average of top
int avgbot = (botl + botr) ; //average of bottom
int avgleft = (topl + botl) ; //average of left
int avgright = (topr + botr) ; //average of right

if (avgtop < avgbot)


{
servoverti.write(servov +1);
if (servov > servovLimitHigh)
{
servov = servovLimitHigh;
}
delay(10);
}
else if (avgbot < avgtop)
{
servoverti.write(servov -1);
if (servov < servovLimitLow)
{
servov = servovLimitLow;
}
delay(10);
}
else
{
servoverti.write(servov);
}

if (avgleft > avgright)


{
servohori.write(servoh +1);
if (servoh > servohLimitHigh)
{
servoh = servohLimitHigh;
}
delay(10);
}
else if (avgright > avgleft)
{
servohori.write(servoh -1);
if (servoh < servohLimitLow)
{
servoh = servohLimitLow;
}
delay(10);
}
else
{
servohori.write(servoh);
}
delay(50);
}

211) Arduino Door Bell


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Resistor 2.21k ohm

× 2
Speaker: 0.25W, 8 ohms

× 1

General Purpose Transistor NPN

× 1

General Purpose Transistor PNP

× 1

Capacitor 22 µF

× 1

SparkFun Pushbutton switch


12mm
× 1

24C512
× 1
ABOUT THIS PROJECT
A doorbell project for Arduino Uno with ATMEGA328P device. The
EEPROM 24C512 is 512Kbits and it can store up to 3 seconds wave
file of 22.050KHz, 8 bits, mono.
The Arduino reads the ROM bytes in a sequential read mode and
stream each byte to the PWM generator at a rate of about 22 KHz. The
I2C bus works at 200 KHz for the purpose of managing to process 22
Kbits per second. Changing the bus frequency changes the speed of the
sound.
The transistors are a push-pull buffer for driving the speaker, any
replacement can be used.
The I2C lib doesn't have a function for sequential read, so I added a
routine.
To load sound file to the eeprom do this:
Convert sound file to .wav PCM 22.050KHz, 8 bits, mono
Change the file name extension from wav to bin.
Load the bin file to the EEPROM Programmer.
SCHEMATICS
CODE
#include <Wire.h>

const int audio = 6; //output D6


const int ring = A2; //ring pushbutton
int ringPB=1; // ring pushbutton status

void setup() {
// put your setup code here, to run once:

pinMode(ring, INPUT_PULLUP);

//PWM Timer0
OCR0A = 64;
TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); //output in
phase, fast PWM mode
TCCR0B = _BV(CS00); // 16MHz/256 = 64KHz

Wire.begin(); // init i2c bus


Wire.setClock(200000); //200khz

void loop()
{
unsigned int i;
ringPB=digitalRead(ring);
if(ringPB==LOW) //pushbutton
{
pinMode(audio, OUTPUT);
//go to address 0
Wire.beginTransmission(0x50);
Wire.write((int)(0)); //MSB of eeprom address
Wire.write((int)(0)); // LSB
Wire.endTransmission();

//start sequential read


TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //start command
while (!(TWCR & (1<<TWINT))); //till interrupt
//write address
TWDR = 0b10100001; //address+read
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))); //till interrupt

//read all the bytes


for (i=0; i<0xfff0; i++)
{
//send ACK
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
while (!(TWCR & (1<<TWINT)));
OCR0A = TWDR; //PWM = eeprom data
}

//send NACK, no-aknowledgement + stop commands ends reading


TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
OCR0A = TWDR;
//stop
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);

pinMode(audio, INPUT); //stop the audio output


}

212) Arduino Auto Fan


COMPONENTS AND SUPPLIES

relay
× 1

fan
× 1
computer fan
9V battery (generic)

× 1

Arduino UNO & Genuino UNO

× 1

lm35
× 1
ABOUT THIS PROJECT

There is one point to which I want to draw attention. When setting up


the circuit I connect the common GND pins. Some fans cannot measure
the extent of trying correctly. If you encounter such a thing, you can
connect GND separately. When I hooked them up separately, it was
solved.
I must say also that with the relay NO, it is necessary to pay attention
to NC pins. NO means "normally open" and NC means "normally
closed". So, if you connect the NO pin, it stops when it reaches 0. If
you connect the NC pin, it stops when it reaches 0 1 runs.
First, let me mention that it produces a value between 0 and 1 volt with
LM35 value as a margin of error; but the way you work with 5V, there
are values that can be high.
That's why we need to inform the Arduino to produce values between 0
and 1.1 volts. Here you analogReference (INTERNAL) are doing with
the command.
When we talk about self-assessing the degree 10mV from each LM35
that 1 ° C corresponds to, we were told to use the Arduino reference to
1,1V. In this way, it is going to have to look at each analog input value ,
like 1.0742 mV. i.e., 10 mV, since it corresponds to 1 ° C; 10 / 1.0742
gives us the value of approximately 9.31.
SCHEMATICS
CODE
// LM35 and relay pins defined
int role=7;
int lm35=A0;

void setup() {

Serial.begin(9600); //Serial comminication started


analogReference(INTERNAL); //arduino 1,1V reference set
pinMode(role,OUTPUT); //Relay is defined as output

void loop() {
int okunanDeger = analogRead(A0); //Read analog value
float derece = okunanDeger / 9.31; //centigrade calculated
Serial.println(derece); //centigrade print on screen
delay(1000); // wait 1 sec

if(derece >25)
digitalWrite(role,HIGH); //relay power on
else
digitalWrite(role,LOW); //relay power off
}

213) DIY Smart Cane Using Arduino


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Buzzer

× 1

Ultrasonic Sensor - HC-SR04 (Generic)


× 1

DC motor (generic)
its not a ordinary motor, it is a micro × 1
vibrating motor that i took from old
celphone.
Jumper wires (generic)

× 1

Slide Switch
Here in this project i used a toggle switch,
but you can use a slide switch . it also work × 1

9V battery (generic)

× 1

9V to Barrel Jack Connector

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Today in this project we are going to make a smart blind stick for
visually impaired persons.
Have you noticed blind people?
Their life is full of risk. They can't walk without the help of others.
Their lives always depends upon others. Let's make something for
them. Yesterday when I was walking to my college, a blind person who
was walking through the street. He faces difficulty walking on that
busy street. Fortunately I could help him at that time. At that moment, I
also thought I needed to do something for blind people. In the evening
of that day I came up with this idea: the smart blind stick. My aim is
that this can be cheap and easy-to-make. Even a kid can make it easily
in a couple of hours from scratch.
Using this smart blind stick, a visually impaired person can walk
without anyone's help. The smart blind stick automatically detects the
obstacle in front of the person and gives a response to the person by
vibrating the stick and with a warning sound.
Through this the blind person can be aware of the obstacles in front of
him.
I used an ultrasonic sensor for detecting the obstacles. It cost me just
10$ to make one.
So, it is cheap and also easy to make - not need for much soldering.
Keep reading to find out how to make it!
Step 1: Collect the Parts
Firstly, we need to collect all the parts that we needed.
Here are the parts you need to collect:
an Arduino Uno
an ultrasonic sensor (HCSR04)
a mini breadboard
a 9 volt battery
a 9 volt battery connector
DC male power jack
a buzzer
some jumper wires
a broken cellphone from scratch
a toggle switch
Other tools and parts used in this project:
3/4 inch diameter PVC pipe (used for making the stick)
3/4 inch diameter PVC elbow
insulation tape
some small screws for mounting the Arduino
screwdriver
utility knife
instant adhesive glue
a box to put your Arduino and other electronics in, or think about it
later
I thinks that's all we needed.
After collecting all the parts that we need, let's go to the next step!
Step 2: Take the Vibrator Motor from a Cellphone
First we need the vibrator motor. Find a broken cellphone.
Do this step with care and patience.
I used a micro vibrator motor from an old broken cellphone that was
lying around my home. The reason I used this: it is very small in size
and almost works with low voltage.
Unscrew the cellphone and disassemble all the parts like shown in the
above images. You can see the vibrator motor placed a side of the
phone's case. Take out the motor carefully from the cellphone.
Please note: different cellphones have different vibrator motor (in size and shape).
Now solder the motor on a small piece of general purpose PCB, then
solder two wires to the terminals of the motor like shown in the above
images.
Now we got the vibrator motor.
Step 3: Wiring the Arduino
Now it's time for wiring the Arduino!
See the above schematics and carefully connect all parts to the
Arduino.
I used a mini breadboard to connect the ultrasonic sensor to the
Arduino using jumper wires. The other parts like the buzzer and motor
are directly connected to the Arduino.
It's pretty easy does not have complicated wiring.
You can see the wiring diagram from the above image. Here I will
explain part by part:
Ultrasonic VCC to Arduino 5v
Ultrasonic GND to Arduino GND
Ultrasonic TRIG to Arduino D12
Ultrasonic ECHO to Arduino D11
Buzzer RED to Arduino D8
Buzzer BLACK to Arduino GND
Vibrator motor pin 1 to Arduino D7
Vibrator motor pin 2 to Arduino GND
9 volt battery RED to Toggle switch pin 1
9 volt battery BLACK to DC male power jack(-)
Toggle switch pin 2 to DC male power jack (+)
Now we finished the wiring!
Step 4: Arduino Sketch
Now it's time for uploading the sketch to the Arduino. The Arduino
code is attached with this project. Just copy and paste the code to your
Arduino IDE and plug your Arduino into the PC. Just click the upload
button. After successfully uploading, unplug the Arduino board.
Step 5: Let's Make the Stick
I used a PVC pipe for making the stick.
If you have a walking stick lying around your home, use that, or else
follow this step. Take a look at the above images to make the stick.
I used a 3/4 inch diameter PVC pipe and a 'L' shaped elbow for making
the stick.
I will describe to you in words how to make one:
First take a PVC pipe (3/4 inch diameter), then cut a piece of one
and half meter.
Take an 'L' shaped elbow and attach it one of the ends of the pipe.
Take another small piece of PVC pipe (10 cm long), then attach it
the other end of the elbow.
Simply glue it.
I just wrapped the stick with black insulation tape. No specific reason
for that except that I like the color black. You can even use paint to get
a cool look.
Step 6: Fitting the Circuit on the Stick
Now its time for fixing everything on the stick.
This is the hardest step in this project. It took me hours to design and
fix the parts onto the stick.
Find a box yourself that we can use to put all the electronics together. I
used a foam board to make a box myself. You can also simply do that (I
don't think you need a explanation for that).
Fix your Arduino into the box, use screws for a strong fixing. Make
two holes for fixing the ultrasonic sensor on the closing lid of the box
as shown in the above image. I fixed the buzzer outside of the box for a
clear sound. I also fixed the toggle switch onto a side of the box and a
small hole for connecting the vibrating motor to Arduino. Fix the
battery inside of the box and connect the power jack to the Arduino.
Mount the ultrasonic sensor on the closing lid of the box. Fix the
buzzer on the top of the box. Take out the vibrator motor to outside of
the box (we need to fix it on the stick's hand). See the above pictures
for how I put together all the parts.
Now attach the box to the stick, you can either use screw or glue it.
Here I used a instant adhesive glue, because it is very strong.
After attaching the box to the stick, take out the vibrator motor and fix
it below the elbow. I used insulation tape to fix the motor.
Step 7: Done
We made the smart blind stick. Make more features for the smart blind
stick and contribute something yourself to humanity. Bring more
automation ideas to help others.

SCHEMATICS
CODE
#define trigPin 13
#define echoPin 12
#define motor 7
#define buzzer 6

void setup()
{ pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(motor, OUTPUT);
pinMode(buzzer,OUTPUT);
}
void loop()
{ long duration, distance;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);


distance = (duration/2) / 29.1;

if (distance < 70) // Checking the distance, you can change the value
{
digitalWrite(motor,HIGH); // When the the distance below 100cm
digitalWrite(buzzer,HIGH);
} else
{
digitalWrite(motor,LOW);// when greater than 100cm
digitalWrite(buzzer,LOW);
} delay(500);
}

214) Arduino How to Drive a 7 Segment Display with HCF4511


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

SparkFun 7-Segment Serial Display


- Red
× 1

HCF4511
× 1

Resistor 10k ohm

× 1

Rotary Encoder with Push-Button

× 1
470 ohm resistor
× 1

Breadboard (generic)

× 1

Jumper wires (generic)

ABOUT THIS PROJECT

1. What is a Seven Segment Display?


A seven-segment display (SSD), or seven-segment indicator, is a form of
electronic display device for displaying decimal numerals that is an
alternative to the more complex dot matrix displays.
Seven-segment displays are widely used in digital clocks, electronic
meters, and other electronic devices for displaying numerical information.
In a simple LED package, typically all of the cathodes (negative terminals)
or all of the anodes (positive terminals) of the segment LEDs are
connected and brought out to a common pin; this is referred to as a
"common cathode" or "common anode" device. Hence a 7 segment plus
decimal point package will only require nine pins (though commercial
products typically contain more pins and/or spaces where pins would go)
in order to match standard IC sockets.
An SSD can be driven using Arduino pins for each LED or using an ad-
hoc driver like the HCF4511. In this way you need only 4 Arduino pins
instead of 8!

2. HCF4511
HCF4511B is a BCD to 7 segment decoder driver able to drive LEDs and
other displays directly.

3. The First Example


As you can see in the datasheet of the HCF4511, in order to drive the
display properly and view numbers from 0 to 9, it is necessary to give a
specific binary sequence in the input ABCD, where A represents the LSB
(Least Significant Bit) and D the MSB (Most Significant Bit).
This first example shows how to increment the numbers that you see on
the display when a button (attached to pin A0) is pressed.
4. Schematic
The schematic used is taken from the datasheet and allows you to drive the
display correctly. Arduino pins 2, 3, 4 and 5 are used as A, B, C and D
input of the HCF4511. When the button is pressed, a counter is increased
and subsequently converted in binary. This corresponds to an increment of
the number shown on the display.

5. The Code
As you can see the code is very simple. Every time the button is pressed,
the counter will be increased and the number's converted to binary!
/*
Example of how to drive a seven segment display using HCF4511 or
similar
This sketch drive the display in order to show a number from 0 to 9
everytime a button connected to A0 is pressed.
author: Arturo Guadalupi
*/
//Declaration of Arduino pins used as HCF4511 inputs
const int A=2;
const int B=3;
const int C=4;
const int D=5;
void setup() {
pinMode(A0, INPUT);
pinMode(A, OUTPUT); //LSB
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT); //MSB
}
int count = 0; //the variable used to show the number
void loop() {
if (digitalRead(A0) == L

SCHEMATICS
CODE
/*
Example of how to drive a seven segment display using HCF4511 or similar

This sketch drive the display in order to show a number from 0 to 9 everytime a button
connected to A0 is pressed.

*/

//Declaration of Arduino pins used as HCF4511 inputs


const int A=2;
const int B=3;
const int C=4;
const int D=5;

void setup() {
pinMode(A0, INPUT);
pinMode(A, OUTPUT); //LSB
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT); //MSB

int count = 0; //the variable used to show the number

void loop() {
if (digitalRead(A0) == LOW) //if button is pressed
{
count++;
delay(200); //the delay prevent from button bouncing
if (count == 10) //we want to count from 0 to 9!
count = 0;
to_BCD(); //convert to binary
}

if (count == 10)
count = 0;

void to_BCD()
{
if (count == 0) //write 0000
{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 1) //write 0001


{
digitalWrite(A, HIGH);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 2) //write 0010


{
digitalWrite(A, LOW);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 3) //write 0011


{
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 4) //write 0100


{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}

if (count == 5) //write 0101


{
digitalWrite(A, HIGH);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}

if (count == 6) //write 0110


{
digitalWrite(A, LOW);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}

if (count == 7) //write 0111


{
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}

if (count == 8) //write 1000


{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
}

if (count == 9) //write 1001


{
digitalWrite(A, HIGH);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
}
}

215) Arduino Smart Phone Controlled Lamp


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

HC-06 Bluetooth Module


× 1

Arduino 2 Channel 5V DC Relay Module


Solid State High Level × 1
Jumper wires (generic)

× 1

Breadboard (generic)

× 1
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)
APPS AND ONLINE SERVICES
MIT App Inventor

Arduino IDE

ABOUT THIS PROJECT

Hi everyone! My next project is How to make smartphone controlled


lamp using Arduino Uno, bluetooth module HC-06 and create Android
App with MIT App Inventor.
Wiring is quite simple and you can easily make all connections.
Creating an App will take about 15 minutes.
Step 1: Requirements
Parts Required:
Arduino Uno R3 Board
Bluetooth module HC-06
Relay module
Jumper wires
Breadboard
Step 2: Wiring and Connections
Make connections as in the wiring diagram image above.
Step 3: Upload the Code
Before uploading the code you have to disconnect Bluetooth module
from Arduino Uno board (pins 0, 1).
Step 4: Creating Android App
For creating an App I used MIT App Inventor, then simply saved it to
my smartphone and installed it.
Creating an App - watch my video - part II
Step 5: Connecting Bluetooth Module
To connect your smartphone to Arduino Bluetooth module HC-06 we
have to enter PIN CODE 1234 or 0000.

SCHEMATICS
CODE
/*
Example of how to drive a seven segment display using HCF4511 or similar

This sketch drive the display in order to show a number from 0 to 9 everytime a button
connected to A0 is pressed.

*/

//Declaration of Arduino pins used as HCF4511 inputs


const int A=2;
const int B=3;
const int C=4;
const int D=5;
void setup() {
pinMode(A0, INPUT);
pinMode(A, OUTPUT); //LSB
pinMode(B, OUTPUT);
pinMode(C, OUTPUT);
pinMode(D, OUTPUT); //MSB

int count = 0; //the variable used to show the number

void loop() {
if (digitalRead(A0) == LOW) //if button is pressed
{
count++;
delay(200); //the delay prevent from button bouncing
if (count == 10) //we want to count from 0 to 9!
count = 0;
to_BCD(); //convert to binary
}

if (count == 10)
count = 0;

void to_BCD()
{
if (count == 0) //write 0000
{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 1) //write 0001


{
digitalWrite(A, HIGH);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 2) //write 0010


{
digitalWrite(A, LOW);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 3) //write 0011


{
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}

if (count == 4) //write 0100


{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}

if (count == 5) //write 0101


{
digitalWrite(A, HIGH);
digitalWrite(B, LOW);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}

if (count == 6) //write 0110


{
digitalWrite(A, LOW);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}

if (count == 7) //write 0111


{
digitalWrite(A, HIGH);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
digitalWrite(D, LOW);
}
if (count == 8) //write 1000
{
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
}

if (count == 9) //write 1001


{
digitalWrite(A, HIGH);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, HIGH);
}
}
216) Arduino Countdown Timer

COMPONENTS AND SUPPLIES

Breadboard (generic)

× 1

Jumper wires (generic)


× 1

SparkFun 7-Segment Serial Display - Red


No breakout board board used in this project
× 1

USB-A to Mini-USB Cable

× 1

Arduino Mega 2560 & Genuino Mega 2560

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

This project was a project designed specifically because I did not have a
timer on hand. To use this project you simply just upload the code to your
arduino (any type will work) you will just need upload the code to the
arduino and the countdown will automatically start. Should you want to
change the total time you will need to change this part of code.
REMEMBER!!! 1000= 1 sec. so 60000 = sec 60 or the equation
(SECx1000) will give you your total number to insert into the place of the
60000. Finally when you press the reset button the counter automatically
restarts.
long n = 60000; //start time -> CAN CHANGE TO WHATEVER TIME
YOU WANT
SCHEMATICS
CODE
//7 segement pin number - 7 segement light - arduino pin number

//pin 11 - A = 12
//pin 7 - B = 10
//pin 4 - C = 8
//pin 2 - D = 7
//pin 1 - E = 6
//pin 10 - F = 11
//pin 5 - G = 9
//pin 3 is decimal

/*
12 11 10 9 8 7
| | | |||
A
---
F| |B
|G|
---
E| |C
| |
--- . dec
D
||||||
123456
*/

//pin 12 - first digit = 1


//pin 9 - second digit = 2
//pin 8 - third digit = 3
//pin 6 fourth digit = 4

const int a = 12;


const int b = 10;
const int c = 8;
const int d = 7;
const int e = 6;
const int f = 11;
const int g = 9;
int p = 0;

int startStopReset = 13;

const int d1 =1;


const int d2 =2;
const int d3 =3;
const int d4 =4;

long n = 60000; //start time -> CAN CHANGE TO WHATEVER TIME YOU WANT
int x = 100;
int del = 55; //delay value

void setup()
{
pinMode(d1, OUTPUT);
pinMode(d2, OUTPUT);
pinMode(d3, OUTPUT);
pinMode(d4, OUTPUT);
pinMode(a, OUTPUT);
pinMode(b, OUTPUT);
pinMode(c, OUTPUT);
pinMode(d, OUTPUT);
pinMode(e, OUTPUT);
pinMode(f, OUTPUT);
pinMode(g, OUTPUT);
pinMode(p, OUTPUT);
pinMode(startStopReset, INPUT);
digitalWrite(startStopReset, HIGH);
}

void loop()
{
digitalWrite (p, HIGH);

clearLEDs();
pickDigit(1);
pickNumber((n/x/1000)%10);
delayMicroseconds(del);

clearLEDs();
pickDigit(2);
pickNumber((n/x/100)%10);
delayMicroseconds(del);

clearLEDs();
pickDigit(3);
dispDec(3);
pickNumber((n/x/10)%10);
delayMicroseconds(del);

clearLEDs();
pickDigit(4);
pickNumber(n/x%10);
delayMicroseconds(del);

n--; //'n++' for stopwatch

if (digitalRead(13) == LOW)
{
n = 60000; //re-start time -> CHANGE TO WHATEVER TIME YOU ORIGONALLY SET
(start time)
}
}

void pickDigit(int x) //changes digit


{
digitalWrite(d1, HIGH);
digitalWrite(d2, HIGH);
digitalWrite(d3, HIGH);
digitalWrite(d4, HIGH);

switch(x)
{
case 1:
digitalWrite(d1, LOW);
break;
case 2:
digitalWrite(d2, LOW);
break;
case 3:
digitalWrite(d3, LOW);
digitalWrite(p, HIGH); //new
break;
default:
digitalWrite(d4, LOW);
break;
}
}

void pickNumber(int x) //changes value of number


{
switch(x)
{
default:
zero();
break;
case 1:
one();
break;
case 2:
two();
break;
case 3:
three();
break;
case 4:
four();
break;
case 5:
five();
break;
case 6:
six();
break;
case 7:
seven();
break;
case 8:
eight();
break;
case 9:
nine();
break;
}
}

void dispDec(int x)
{
digitalWrite(p, LOW);
}

void clearLEDs()
{
digitalWrite(a, LOW);
digitalWrite(b, LOW);
digitalWrite(c, LOW);
digitalWrite(d, LOW);
digitalWrite(e, LOW);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
digitalWrite(p, LOW);
}

void zero()
{
digitalWrite(a, HIGH);
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, HIGH);
digitalWrite(e, HIGH);
digitalWrite(f, HIGH);
digitalWrite(g, LOW);
}
void one()
{
digitalWrite(a, LOW);
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, LOW);
digitalWrite(e, LOW);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
}

void two()
{
digitalWrite(a, HIGH);
digitalWrite(b, HIGH);
digitalWrite(c, LOW);
digitalWrite(d, HIGH);
digitalWrite(e, HIGH);
digitalWrite(f, LOW);
digitalWrite(g, HIGH);
}

void three()
{
digitalWrite(a, HIGH);
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, HIGH);
digitalWrite(e, LOW);
digitalWrite(f, LOW);
digitalWrite(g, HIGH);
}

void four()
{
digitalWrite(a, LOW);
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, LOW);
digitalWrite(e, LOW);
digitalWrite(f, HIGH);
digitalWrite(g, HIGH);
}

void five()
{
digitalWrite(a, HIGH);
digitalWrite(b, LOW);
digitalWrite(c, HIGH);
digitalWrite(d, HIGH);
digitalWrite(e, LOW);
digitalWrite(f, HIGH);
digitalWrite(g, HIGH);
}

void six()
{
digitalWrite(a, HIGH);
digitalWrite(b, LOW);
digitalWrite(c, HIGH);
digitalWrite(d, HIGH);
digitalWrite(e, HIGH);
digitalWrite(f, HIGH);
digitalWrite(g, HIGH);
}

void seven()
{
digitalWrite(a, HIGH);
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, LOW);
digitalWrite(e, LOW);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
}

void eight()
{
digitalWrite(a, HIGH);
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, HIGH);
digitalWrite(e, HIGH);
digitalWrite(f, HIGH);
digitalWrite(g, HIGH);
}

void nine()
{
digitalWrite(a, HIGH);
digitalWrite(b, HIGH);
digitalWrite(c, HIGH);
digitalWrite(d, HIGH);
digitalWrite(e, LOW);
digitalWrite(f, HIGH);
digitalWrite(g, HIGH);
}

217) Measure LUX With Arduino Using BH1750


COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

Adafruit bh1750 lux sensor


ABOUT THIS PROJECT

If you are looking to test a lux value of light with Arduino, then this
project is suitable for you its easy and cool! Just connect the BH1750
module, upload the code, and run the serial monitor.

SCHEMATICS

CODE
#include <Wire.h>
#include <BH1750.h>

BH1750 lightMeter;

void setup(){
Serial.begin(9600);
lightMeter.begin();
Serial.println("Running...");
}

void loop() {
uint16_t lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
delay(1000);
}
218) Arduino Outomatic Door and Counter Prototype

COMPONENTS AND SUPPLIES

Arduino Mega 2560 & Genuino


Mega 2560
× 1
Servos (Tower Pro MG996R) × 2

Adafruit Standard LCD - 16x2


White on Blue
× 1

Ultrasonic Sensor
× 2
NECESSARY TOOLS AND MACHINES
Soldering iron (generic)

Hot glue gun (generic)

ABOUT THIS PROJECT

The project is composed of different common components like the


servo motor, ultrasonic sensor, and an output LCD Display. The
complete project works in the way that all movements detected on the
left door, counts the counter up, making it say that a specific number of
person is inside the establishment, on the other hand, counting down
signifies that this sum of persons have left the establishment
First Draft of the Project
The project first planned. Dimensions were written out and the
mechanism was also drawn. The task was to emulate the person counter
for establishments in real life.
Housing for the Project
1. We got some illustration boards and hard cardboards then trimmed it
to the exact dimensions as displayed above.
2. The trimmed boards were placed together using a Glue Gun.
3. Once the boards are shaped like a building, we then glued a stick to
the Servo's Arm. The stick will act as an extension to the servo's arm
that controls the opening and the closing of the doors.
4. After attach the servos to the backside of the housing with Hot Glue.
5. Test if the stick and servo movements are precise.
6. Attach the LCD on the front side of the board.
7. Attach a Ultrasonic Sensor on one side of the small roof deck like
structure and then attach the other inside. Make sure that you measured
the distance between the floor and the ultrasonic sensor so that the
sensing input will be assured.
Wiring
1. Wire the LCD first to a breadboard hidden inside the Housing.
2. Connect the Ultrasonic Wires also to the Breadboard.
3. The Servo Wire will go directly to the Arduino Mega 2560.
4. After wiring do a test run of the program
5. Debug the code depending on your build
#Note: The hot glue used on the Servo sometimes gets unglued due to
the repetitive movement of the Servo. You might want to check them
every once in a while if they are still glued

Final Project Displayed


The final look of the project after we presented it to our professor.

Input - Process - Output Diagram of the Project


The IPO Diagram displays the basic hardware needs of the project.

SCHEMATICS
CODE
//Adds libraries needed for the project
#include <Servo.h>
#include <NewPing.h>
#include <LiquidCrystal.h>

//defines constants for the pin layout


#define trigPin1 19
#define echoPin1 20
#define trigPin2 23
#define echoPin2 24
#define maxd 50
#define doorSensor 2

//lcd as variable for LiquidCrystal function


LiquidCrystal lcd(36,38,40,42,44,46);

//variables for telling time in Ultrasonic Sensing


long duration, distance;
int pinged;

//created variables to hold servo function


Servo myservo;
Servo myOtherServo;

//variable for counting persons


int incoming = 0;
int outgoing = 0;
int inside = 0;

//Newping sonar array containg 2 various ultrasonic sensor pin config


NewPing sonar[doorSensor] = {
NewPing (trigPin1, echoPin1, maxd), // NewPing setup of pins and
maximum distance.
NewPing (trigPin2, echoPin2, maxd) // NewPing setup of pins and
maximum distance .
};

void setup(){
//Start Serial
Serial.begin(9600);

//Initiate LCD
lcd.begin(16,2);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Hello");

//attach pins to servos


myservo.attach(9);
myservo.write(0);
myOtherServo.attach(10);
myOtherServo.write(80);
// attachInterrupt(digitalPinToInterrupt(20),openEnter,RISING);
// attachInterrupt(digitalPinToInterrupt(21),openExit,RISING);
}
void loop(){

printToLCD();
getPing();
// derf = incoming;
}

void getPing(){
delay(50); // Wait 50ms between pings (about 20 pings/sec).
29ms should be the shortest delay between pings.
unsigned int uS = sonar[0].ping(); // Send ping, get ping time in
microseconds (uS).
// Serial.print("Ping1: ");
pinged = uS / US_ROUNDTRIP_CM;
// Serial.print(pinged); // Convert ping time to distance in cm and print
result (0 = outside set distance range)
// Serial.println("cm");

if(pinged < 8){


openEnter();
outgoing++;
}
if(pinged>8){
closeEnter();
}

delay(50); // Wait 50ms between pings (about 20 pings/sec).


29ms should be the shortest delay between pings.
uS = sonar[1].ping(); // Send ping, get ping time in microseconds (uS).
// Serial.print("Ping2: ");
pinged = uS / US_ROUNDTRIP_CM;
// Serial.print(pinged); // Convert ping time to distance in cm and print
result (0 = outside set distance range)
// Serial.println("cm");
if(pinged < 10){
openExit();
incoming++;
}
if(pinged>10){
closeExit();
}

void openEnter(){
myOtherServo.write(0);
delay(10);
myOtherServo.write(80);
delay(100);}
void closeEnter(){
myOtherServo.write(80);
delay(10);
myOtherServo.write(0);
delay(100);}
void openExit(){
myservo.write(80);
delay(10);
myservo.write(0);
delay(100);
}
void closeExit(){
myservo.write(0);
delay(10);
myservo.write(80);
delay(100);}
void printToLCD(){
if (inside == 0){
// delay(100);
closeEnter();

}
inside = incoming - outgoing;

if(inside < 0){


closeEnter();
delay(500);
outgoing = 0;
incoming=0;
myOtherServo.attach(54);
inside = 0;}
if(inside == 1){
myOtherServo.attach(10);}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Customer Inside: ");
lcd.setCursor(0,1);
lcd.print(inside);
Serial.println(inside);
}
219) Security System And Acsess Control With Arduino And RFID
COMPONENTS AND SUPPLIES

Arduino UNO & Genuino UNO

× 1

rfid522a
× 1

lcd 20*4
× 1

microservo 9g
× 1

SparkFun Breadboard Power Supply 5V/3.3V

× 1

Resistor 221 ohm

× 2

Rotary potentiometer (generic)

× 1

Buzzer

× 1

LED (generic)

× 2

Jumper wires (generic)

× 30

Breadboard (generic)

× 1
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Instead of using a matricial keyboard, to enter passwords and to allow


access to a door or to drive an electronic device, now we will use a RFID
(Radio Frequency Identifier Device). We also will use a LCD Display
with 20 character and 4 lines to show some messages from the system,
besides a servo-motor to drive an mechanical device like (door's locks,
turnstile, etc...). Users will have cards or tags registered to access the
system. When approaching the card/tag to the RFID sensor (approximately
6 cm), the serial number of this card/tag is detected and so compared with
a serial number that are recorded in the software or in a database on a
memory card; if it is a registered serial number, the system will release the
entry of this user. A green LED will be lit and some messages will be
appearing in the LCD display (user recognition and user welcome), the
buzzer will give access granted sound, besides that a servo will be drived
to release a mechanical device. Otherwise, the system does not release the
user access, and a warning red LED will be lit and will be showed a
message on the LCD advising the user to contact the account
manager.During this process of release or rejection of users,
characteristics beeps will be played on a buzzer (just like a sound
announcement).
Interconnections from the RFID to the Arduino pins:
Reset > Pin 8
SDA > Pin 10
MOSI > Pin 11
MISO > Pin 12
SCK > Pin 13
Ground > Ground
3.3v > 3.3v
Interconnections from the DISPLAY to the Arduino pins:
Vss > Ground
Vdd > +5v
V0 > one pin of potntiometer | 2nd pin of pot to 5v |3rd pin to ground
Rs > Pin 7
R/w > Ground
E > Pin 6
D0,D1,D2,D3 > no connection
D4 > Pin 5
D5 > Pin 4
D6 > Pin 3
D7 > Pin 2
A > +5v
K > ground
Interconnections from the SERVO to the Arduino pins:
Control pin > Pin 9
Vcc > +5v
Ground > Ground
Interconnections from the BUZZER to the Arduino pins:
Positive pin > Pin A2
Ground > Ground
Interconnections from the GREEN LED to the Arduino pins:
Positive pin > Pin A1
Ground > Ground
Interconnections from the GREEN LED to the Arduino pins:
Positive pin > Pin A0
Ground > Ground
Upload the given code to the Arduino. Connect the components:
SCHEMATICS
CODE
#include <LiquidCrystal.h> //lcd library
/*Thudangi*/
#include <Servo.h> //servo library
int servoPin = 9;
Servo Servo1;

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

int red=A0;
int green=A1;

#include <MFRC522.h> // RFID Library


#include <SPI.h> // For communication via SPI with the Module
#define SDAPIN 10 // RFID Module SDA Pin is connected to the UNO 10 Pin
#define RESETPIN 8 // RFID Module RST Pin is connected to the UNO 8 Pin
byte FoundTag; // Variable used to check if Tag was found
byte ReadTag; // Variable used to store anti-collision value to read Tag information
byte TagData[MAX_LEN]; // Variable used to store Full Tag Data
byte TagSerialNumber[5]; // Variable used to store only Tag Serial Number
byte GoodTagSerialNumber[5] = {0x0E, 0x4A, 0x79, 0x21}; // The Tag S/N. give your rfid
tag identity code here

MFRC522 nfc(SDAPIN, RESETPIN); // Init of the library using the UNO pins declared
above

void setup() {
Servo1.attach(servoPin);
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
lcd.begin(20, 4);
// Print a message to the LCD.
lcd.setCursor(0,0);
lcd.print("RFID SECURITY SYSTEM"); // give here the comments you need show the
display
delay(200);
lcd.setCursor(2,1);
lcd.print(" PROJECT DONE BY "); // give here the comments you need show the display
delay(200);
lcd.setCursor(0,3);
lcd.print(" S6 ELS 2014-2017"); // give here the comments you need show the display
delay(1000);
lcd.setCursor(0,2);
lcd.print(" LIJIN ASHOK "); // give here the comments you need show the display
delay(2000);
lcd.setCursor(0,2);
lcd.print(" MIDHUN M S"); // give here the comments you need show the display
delay(2000);
lcd.setCursor(0,2);
lcd.print(" PRABHU Y RAJ"); // give here the comments you need show the display
delay(2000);
lcd.setCursor(0,2);
lcd.print(" SARATH P "); // give here the comments you need show the display
delay(2000);
lcd.setCursor(0,2);
lcd.print(" SREEJITH R S "); // give here the comments you need show the display
delay(2000);
pinMode(red, OUTPUT);
pinMode(green, OUTPUT);
SPI.begin();
Serial.begin(9600);

// Start to find an RFID Module


Serial.println("Looking for RFID Reader");
nfc.begin();
byte version = nfc.getFirmwareVersion(); // Variable to store Firmware version of the
Module

// If can't find an RFID Module


if (! version) {
Serial.print("Didn't find RC522 board.");
while(1); //Wait until a RFID Module is found
}

// If found, print the information about the RFID Module


Serial.print("Found chip RC522 ");
Serial.print("Firmware version: 0x");
Serial.println(version, HEX);
Serial.println();
}

void loop() {
Servo1.write(0);
delay(300);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("RFID SECURITY SYSTEM");
lcd.setCursor(4,3);
lcd.print("SHOW YOUR ID");
lcd.noDisplay();
delay(200);
lcd.display();
delay(250);
String GoodTag="False"; // Variable used to confirm good Tag Detected

// Check to see if a Tag was detected


// If yes, then the variable FoundTag will contain "MI_OK"
FoundTag = nfc.requestTag(MF1_REQIDL, TagData);

if (FoundTag == MI_OK) {
delay(200);

// Get anti-collision value to properly read information from the Tag


ReadTag = nfc.antiCollision(TagData);
memcpy(TagSerialNumber, TagData, 4); // Write the Tag information in the
TagSerialNumber variable

Serial.println("Tag detected.");
Serial.print("Serial Number: ");
for (int i = 0; i < 4; i++) { // Loop to print serial number to serial monitor
Serial.print(TagSerialNumber[i], HEX);
Serial.print(", ");
}
Serial.println("");
Serial.println();

// Check if detected Tag has the right Serial number we are looking for
for(int i=0; i < 4; i++){
if (GoodTagSerialNumber[i] != TagSerialNumber[i]) {
break;
}
if (i == 3) {
GoodTag="TRUE";
}
}
if (GoodTag == "TRUE"){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("RFID SECURITY SYSTEM");
lcd.setCursor(3, 1);
lcd.print("ACCESS GRANTED");
lcd.setCursor(0,3);
digitalWrite(A1, HIGH);
lcd.print(" +----WELCOME----+");
digitalWrite(A2, HIGH);
delay(300);
digitalWrite(A2, LOW);
delay(300);
digitalWrite(A2, HIGH);
delay(300);
digitalWrite(A2, LOW);
delay(300);
digitalWrite(A2, HIGH);
delay(300);
digitalWrite(A2, LOW);
delay(300);
digitalWrite(A2, HIGH);
delay(300);
digitalWrite(A2, LOW);
delay(300);
digitalWrite(A2, HIGH);
delay(300);
digitalWrite(A2,LOW);
Servo1.write(180);
delay(7000);
Servo1.write(0);
digitalWrite(A1, LOW);
}
else {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("RFID SECURITY SYSTEM");
lcd.setCursor(3, 1);
lcd.print("ACCESS DENIED");
digitalWrite(A1,LOW);
delay(100);
lcd.setCursor(0,3);
lcd.print(" UNAUTHORIZED ENTRY");
digitalWrite(A2, HIGH);
delay(150);
digitalWrite(A2, LOW);
delay(150);
digitalWrite(A2, HIGH);
delay(150);
digitalWrite(A2, LOW);
delay(150);
digitalWrite(A2, HIGH);
delay(150);
digitalWrite(A2,LOW);
delay(150);
digitalWrite(A2, HIGH);
delay(150);
digitalWrite(A2, LOW);
delay(150);
digitalWrite(A2, HIGH);
delay(150);
digitalWrite(A2,LOW);
digitalWrite(A0, HIGH);
delay(3000);
digitalWrite(A0, LOW);
}
delay(200);
}
}

220) Frequency and Duty Cycle Measurement Using Arduino


COMPONENTS AND SUPPLIES
Arduino UNO & Genuino UNO

× 1

Alphanumeric LCD, 20 x 4

× 1
NECESSARY TOOLS AND MACHINES
Breadboard, 270 Pin
APPS AND ONLINE SERVICES
Arduino IDE

ABOUT THIS PROJECT

Arduino has several applications. We may find its application in many


different fields and areas. It can be used in measurement field also to
measure electrical quantities (like voltage, current, power etc) or
physical quantities (like temperature, moisture, light intensity, humidity
etc) or electronic component values etc.
The given article demonstrates how to measure frequency and duty
cycle of pulses using arduino. Frequency measurement is required in so
many different applications. In communication field frequency
measurement is at most essential. Duty cycle is also an important
parameter to measure because it gives % of pulse width – means ON
time of pulse. In DC motor speed control and servo motor angle control
it is required to measure width of pulse. Also the pulse width is
measured to check the symmetry of pulse in some of the application
like digital signal receiver, repeaters etc. So let us see how we can use
arduino to measure frequency and duty cycle of pulses. In given
project, the arduino measures frequency, ON time, OFF time and duty
cycle of pulses and displays them on 16x4 LCD
Description:
As shown in above figure there are only two major components in the
circuit (1) arduino UNO development board and (2) 16x4 LCD display
· The pulses are directly given as an input to digital pin 7 of arduino
· The Rs and En pins of LCD are connected to digital pins 9 and 8
respectively of arduino board. Rw pin is connected to ground
· Last four data pins D4 – D7 are connected to arduino pins 10, 11, 12
and 13
· The anode pin of back light LED (pin 15) and Vcc pin (2) of LCD are
given 5 V supply through arduino board
· Cathode of back light LED (pin 16) and Vss pin (1) are connected to
ground
· One1 K pot is connected to Vee pin to vary LCD contras
Circuit operation:
· When arduino board is given supply through USB, four parameters
are displayed on LCDas “freq:Ton:Toff:Duty: “on each row as shown
· Now when pulses are fed to pin 7, the arduino first wait for pulse to
be high. When it becomes high it calculates the time period (in micro
second) for which the pulse remains high. This it Ton time
· Then it calculated time period (in micro second) for which pulse
remains low. This is Toff time
· Then it add these two time intervals to get total time – means period
· From total time the arduino calculates frequency as
Frequency = 1 / time
· And from Ton and Toff it calculates duty as
Duty = Ton / (Ton + Toff)
· Then it displays all four parameters on LCD
· Again after 1 second it repeats same procedure
· So it continuously measures change in frequency and duty cycle of
pulse

SCHEMATICS
CODE
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 10, 11, 12, 13);


#define pulse_ip 7
int ontime,offtime,duty;
float freq,period;

void setup()
{
pinMode(pulse_ip,INPUT);
lcd.begin(16, 4);
lcd.clear();
lcd.print("Freq:");
lcd.setCursor(0,1);
lcd.print("Ton:");
lcd.setCursor(0,2);
lcd.print("Toff:");
lcd.setCursor(0,3);
lcd.print("Duty:");
}
void loop()
{
ontime = pulseIn(pulse_ip,HIGH);
offtime = pulseIn(pulse_ip,LOW);
period = ontime+offtime;
freq = 1000000.0/period;
duty = (ontime/period)*100;
lcd.setCursor(4,1);
lcd.print(ontime);
lcd.print("us");
lcd.setCursor(5,2);
lcd.print(offtime);
lcd.print("us");
lcd.setCursor(5,0);
lcd.print(freq);
lcd.print("Hz");
lcd.setCursor(6,3);
lcd.print(duty);
lcd.print('%');
delay(1000);
}

You might also like