TIC TAC TOE with Arduino DUE and 4.3″ TFT

This is the wellknown tic-tac-toe game, ordered by my son for waisting some of our free time…  A 4.3″ touch TFT LCD, an Arduino DUE and some lines of code are the ingredients of this weekend project.

For code and libraries, click here:

https://drive.google.com/open?id=0B_CGrhtJ7yX5LWJ2ZUNkcGZtQjQ

Advertisements

3 DIGITS VOLTMETER WITH PIC18F1320

18f1320_voltmeter

https://postimg.org/image/sy5g6cq77/

This is a small, hand-made, 3 digits voltmeter with PIC18F1320. The voltage is displayed on three common anode 7 segments LED displays of your choise. They are multiplexed and driven by small transistors. The maximum input voltage is 30 VDC and can be trimmed with a small trimmer resistor that changes the ratio between the two resistors of the input voltage divider. The analog input of the μC is protected by a small zenner diode rated at 5.1 volts. As result, you can see volts with one decimal digit.

The displays need current limiting resistors (R8-R15) in series with the μC outputs. Their values depend on the specific type of display you gonna use. I used resistor networks of 220 Ohms. They can be clearly  viewed in the next five pictures.

The circuit is supplied by an LM7805 regulator and is protected from opposite polarity with a diode.  The PIC18F1320 is a little bit overkill for such a circuit, but I had it “sitting” in my drawer. Everything was assembled on a small piece of breadboard and wired with Kynar wire. For long lasting opperation, a small heatsink is good to be placed on the regulator. Some pictures of this one-afternoon project:

2014_10_17_22_26_272014_10_17_22_25_112014_10_17_22_24_432014_10_17_22_24_032014_10_17_22_23_242014_10_17_22_21_342014_10_17_22_21_062014_10_17_22_19_44

The code was developed with MPLAB IDE and HI-TECH C Compiler and is free-to-use for anyone who desires to make this mini voltmeter. Just use the link below:

https://drive.google.com/open?id=0B_CGrhtJ7yX5cGhiN3pfN3M0YXM

In this link, you can find seperate folders for firmware and hardware. The schematic was designed with Altium DXP, but there is no PCB.

There is also a github repository at https://github.com/manolena/PIC18F1320-mini-voltmeter.

Have fun!

DIY SOLDERING STATION WITH ARDUINO NANO AND 4×20 LCD

Free counters!

20160413_105504

This is a more simpler design than the DIY SMD SOLDERING STATION WITH AVR (MEGA2560 VERSION) due to the controller core (Arduino NANO instead of MEGA2560), the UI (a 4 rows / 20 characters LCD instead of the TFT)  and the supporting of only PTC type soldering irons. The power supply is still separated (external power pack at 24V used).

All the information for the user is presented continuously  and simultaneously for the actual temperature and desired temperature by the form of bargraph and numbers. For the present, only the Celsius scale is supported but I am still working on updated version with Fahrenheit scale and a very simple menu function for making the adjustments.

The final view of this simple construction is like the following:

4x20_2

I made all the necessary files for the PCB and a good friend of mine (Kostas), the order for ten prototypes. The design was a clear Through Hole project in order to be easily constructed as kit even from young people. In the near future, I will write a very easy-to-read guide for assembling and programming.

http://www.pcbway.com/project/share/Manolena_SMD_Solder_Station_with_Arduino_Nano.html

034343669

I thank Kostas for the kind offer of the prototype PCB and also the spread of this project to other friends. 

The schematic is the following (also in .pdf):

Nano_1

Nano_1.pdf

The PCB is the following:

Nano_1.png

All relative files (Altium files, Gerber files, BOM, Arduino libraries, firmware) can be freely used and can be found here:

https://github.com/manolena/DIY-Soldering-Station-w-Arduino-Nano-4×20-LCD

UPDATE 14 AUG 2016:

The updated version of the soldering station is a new design with the implementation of an Arduino Micro PRO instead of Nano. The overall dimensions have been reduced and the code was re-written to support a small serial I2C OLED display.

PRO_1

PRO_2PRO_4PRO_6

IMG_20160804_234127IMG_20160804_233842IMG_20160804_233832IMG_20160804_133948PRO_5

 

To see the relative Altium files (.SchDoc, .PcbDoc, CAM, gerbers, schematic & component libraries), just right-click and save as .zip the following file:

PRO MICRO

 

 

 

Ardu-Clock

Free counters!

2014-03-03 08.29.43

This clock is based on an ATMega644 micro controller. It’s user interface consists of a 4×20 characters LCD and navigation tactile push buttons. It provides real time clock with date and ambient temperature and can be programmed for a repeating alarm on a weekday basis. This version is still a beta one, so I’m still working on it.

2014-03-03 08.33.11

The time is presented on the top 3 rows of the LCD and a complete data for time, date and temperature scrolls on the lower 4th row of the screen. There is also a bit of information (i.e. a star character is appeared on the left if the alarm is enabled and the “am-pm” info on the right.

2014-03-03 08.33.41

The temperature is presented in Celsius centigrade and appears alternately with the time information every few seconds.

2014-03-05 09.48.45                    2014-03-05 09.48.08

2014-03-05 09.47.47

The project was constructed on a prototype pcb by hand. The small unit on the left picture is a machined piece of pcb on a LPKF CNC and supports the RTC and temperature sensor, based on ST’s M41T80 and TI’s LM75 chips. There is also a small piece of pcb holding the buttons and a buzzer for the audible signals (alarms and function or button beeps.

2014-03-03 08.32.31

The code includes menus for adjusting the time, the date and the alarms schedule on a weekly basis. The Alexander Brevig‘s MenuBackend library helped a lot building the menus section.

 

My YouTube channel:

https://www.youtube.com/channel/UCjd0xwRz7vinbH4ihhJV2Kw

The code (very “beta” version, never finished):

#include <avr/eeprom.h>
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#include <TimerOne.h>
#include <MsTimer2.h>
#include <MenuBackend.h>
#include <AnalogDebounce.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// ===================================================================
#if defined(__AVR_ATmega644P__)
#define LM75_ADDRESS 0x4F
#else
#define LM75_ADDRESS 0x48
#endif
#define M41T80_I2C_ADDRESS 0x68
#define M24C01_I2C_ADDRESS 0x57
#define M24C01_I2C_READ_ADDRESS 0xAF

#if defined(__AVR_ATmega644P__)
#define ANALOG_KEYS A7
#define BACKLIT_PIN 15
#define BUZZER_PIN 4
#else
#define ANALOG_KEYS A0
#define BUZZER_PIN 10
#endif

#define DELAY_1 1000
#define DELAY_2 2000
#define DELAY_3 3000
#define Row0 0
#define Row1 1
#define Row2 2
#define Row3 3
#define A_ 10
#define B_ 11
#define C_ 12
#define D_ 13
#define E_ 14
#define F_ 15
#define G_ 16
#define H_ 17
#define I_ 18
#define J_ 19
#define K_ 20
#define L_ 21
#define M_ 22
#define N_ 23
#define O_ 24
#define P_ 25
#define Q_ 26
#define R_ 27
#define S_ 28
#define T_ 29
#define U_ 30
#define V_ 31
#define W_ 32
#define X_ 33
#define Y_ 34
#define Z_ 35
#define BLANK 36
#define SET 254
#define RESET 206
#define ARROW 247

#define B 0x20
#define INTERVAL_SAMPLE 10
#define N_DECIMAL_POINTS_PRECISION (10) // n = 3. Three decimal points.

#define ALARM_HOUR_EEPROM_ADDRESS 0x00
#define ALARM_MINUTE_EEPROM_ADDRESS 0x02
#define ALARM_FLAG_EEPROM_ADDRESS 0x05

// ===================================================================
#define RIGHT 1
#define UP 2
#define DOWN 3
#define LEFT 4
#define SELECT 5
#define ESCAPE 6
#define NONE 0
// ===================================================================
const int transmit_pin = 12;

byte msecond, second, minute, hour, dayOfWeek, dayOfMonth, month, year;
int hourBuffer, minuteBuffer, secondBuffer, dayOfWeekBuffer, dateBuffer, monthBuffer, yearBuffer = 0;

byte alarmDayOfWeek, alarmHour, alarmMinute;
int alarmDayOfWeekBuffer, alarmHourBuffer, alarmMinuteBuffer = 0;
boolean alarmFlag = 0;

char timeBuffer[40];
char dataBuffer[60];
char *Mon[] = {
“JAN”,”FEB”,”MAR”,”APR”,”MAY”,”JUN”,”JUL”,”AUG”,”SEP”,”OCT”,”NOV”,”DEC”};
char *Day[] = {
“SUN”,”MON”,”TUE”,”WED”,”THU”,”FRI”,”SAT”};
char *DAY[] = {
“MO,”,”TU,”,”WE,”,”TH,”,”FR,”,”SA,”,”SU”,” “};
boolean colonFlag = false;
boolean initial = 0;
int BUTTON, Button;
float temperature;
float farenheit;
boolean bigNumbers = 0;
unsigned long previousMillis = 0;
unsigned long displayMillis = 0;
boolean showInterval;
long interval = 500;
int integerPart;
int decimalPart;
const int MESSAGE_LENGTH = sizeof(timeBuffer);
const int DATA_LENGTH = sizeof(dataBuffer);
const int DISPLAY_WIDTH = 20;
int g_nPosition = 0;
int line = 1;

typedef struct
{
boolean MONDAY_ALARM_FLAG :
1;
boolean TUESDAY_ALARM_FLAG :
1;
boolean WEDNESDAY_ALARM_FLAG :
1;
boolean THURSDAY_ALARM_FLAG :
1;
boolean FRIDAY_ALARM_FLAG :
1;
boolean SATURDAY_ALARM_FLAG :
1;
boolean SUNDAY_ALARM_FLAG :
1;
}
flags;

flags FLAGS;

int buildFlags;
// ===================================================================
#if defined(__AVR_ATmega644P__)
LiquidCrystal lcd(3, 1, 0, 23, 22, 21, 20);
#else
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);//
#endif
AnalogDebounce Buttons(ANALOG_KEYS, readButtons);
// ===================================================================
// The routine to create the custom characters in the LCD
void DefineLargeChar()
{
// Define Custom Characters

uint8_t cc1[8] = { // Custom Character 1
B11100,
B11110,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};

uint8_t cc2[8] = { // Custom Character 2
B11111,
B11111,
B11111,
B11111,
B11111,
B00000,
B00000,
B00000
};

uint8_t cc3[8] = { // Custom Character 3
B00000,
B00000,
B00000,
B11111,
B11111,
B11111,
B11111,
B11111
};

uint8_t cc4[8] = { // Custom Character 4
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B01111,
B00111
};
/*
uint8_t cc4[8] = { // Custom Character 4
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000
};
*/
uint8_t cc5[8] = { // Custom Character 5
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B00000,
B00000
};

uint8_t cc6[8] = { // Custom Character 6
B00000,
B11111,
B11111,
B11111,
B11111,
B11111,
B00000,
B00000
};

uint8_t cc7[8] = { // Custom Character 7
B00000,
B11100,
B11110,
B11111,
B11111,
B11111,
B11111,
B11111
};
/*
uint8_t cc7[8] = { // Custom Character 7
B00000,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
*/
uint8_t cc8[8] = { // Custom Character 8
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};

// send custom characters to the display
lcd.createChar(1,cc1);
lcd.createChar(2,cc2);
lcd.createChar(3,cc3);
lcd.createChar(4,cc4);
lcd.createChar(5,cc5);
lcd.createChar(6,cc6);
lcd.createChar(7,cc7);
lcd.createChar(8,cc8);
}
// ===================================================================
// 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z BLANK
char bn1[]={
8,2,1, 2,1,B, 2,2,1, 2,2,1, 3,B,8, 8,2,2, 8,2,2, 2,2,8, 8,2,1, 8,2,1, 8,2,1, 8,2,1, 3,2,2, 8,2,1, 8,2,2, 8,2,2, 8,2,1, 8,B,8, B,8,B, B,B,8, 8,B,8, 8,B,B, 8,3,1, 8,B,1, 8,2,1, 8,2,1, 8,2,1, 8,2,1, 8,2,5, 2,8,2, 8,B,8, 8,B,8, 8,B,8, 8,B,8, 8,B,8, 2,2,1, B,B,B};
char bn2[]={
8,B,8, B,8,B ,3,2,2, B,6,1, 4,3,8, 5,6,7, 8,6,7, B,3,2, 8,6,8, 5,6,8, 8,6,8, 8,6,1, 8,B,B, 8,B,8, 8,6,B, 8,6,B, 8,B,3, 8,6,8, B,8,B, B,B,8, 8,6,2, 8,B,B, 8,B,8, 8,4,8, 8,B,8, 8,2,2, 8,B,8, 8,3,8, 2,2,1, B,8,B, 8,B,8, 8,B,8, 8,B,8, B,6,B, 2,3,2, B,6,B, B,B,B};
char bn3[]={
4,3,8, 3,8,3, 8,3,3, 3,3,8, B,B,8, 4,3,8, 4,3,8, B,8,B, 4,3,8, B,B,8, 8,B,8, 8,3,8, 4,3,3, 8,3,8, 8,3,3, 8,B,B, 4,3,8, 8,B,8, B,8,B, 4,8,B, 8,B,1, 8,3,3, 8,B,8, 8,B,8, 4,3,8, 8,B,B, 4,3,7, 8,B,1, 4,3,8, B,8,B, 4,3,8, 2,3,2, 4,2,8, 8,B,8, B,8,B, 4,3,3, B,B,B};
/*
// Array index into parts of big numbers. Numbers consist of 9 custom characters in 3 lines
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
char bn1[]={1,2,1, 3,1,4, 2,2,1, 2,2,1, 1,4,1, 1,2,2, 1,2,2, 2,2,1, 1,2,1, 1,2,1, 1,2,1, 1,2,3, 3,2,2, 1,2,3, 1,2,2, 1,2,2};
char bn2[]={1,4,1, 4,1,4, 7,6,5, 6,6,1, 5,6,1, 5,6,7, 1,6,7, 4,4,1, 1,6,1, 5,6,1, 1,2,1, 1,2,1, 1,4,4, 1,4,1, 1,2,4, 1,2,4};
char bn3[]={1,3,1, 3,1,3, 1,3,3, 3,3,1, 4,4,1, 3,3,1, 1,3,1, 4,4,1, 1,3,1, 3,3,1, 1,4,1, 1,3,2, 2,3,3, 1,3,2, 1,3,3, 1,4,4};
*/
// ===================================================================
void printOneLetter(char letter, uint8_t position)
{
// Print position is hardcoded

// Line 1 of the one digit number
lcd.setCursor(position,0);
lcd.write(bn1[letter*3]);
lcd.write(bn1[letter*3+1]);
lcd.write(bn1[letter*3+2]);

// Line 2 of the one-digit number
lcd.setCursor(position,1);
lcd.write(bn2[letter*3]);
lcd.write(bn2[letter*3+1]);
lcd.write(bn2[letter*3+2]);

// Line 3 of the one-digit number
lcd.setCursor(position,2);
lcd.write(bn3[letter*3]);
lcd.write(bn3[letter*3+1]);
lcd.write(bn3[letter*3+2]);
}
// ===================================================================
void printOneNumber(uint8_t digit, uint8_t position)
{
// Print position is hardcoded

// Line 1 of the one digit number
lcd.setCursor(position,0);
lcd.write(bn1[digit*3]);
lcd.write(bn1[digit*3+1]);
lcd.write(bn1[digit*3+2]);

// Line 2 of the one-digit number
lcd.setCursor(position,1);
lcd.write(bn2[digit*3]);
lcd.write(bn2[digit*3+1]);
lcd.write(bn2[digit*3+2]);

// Line 3 of the one-digit number
lcd.setCursor(position,2);
lcd.write(bn3[digit*3]);
lcd.write(bn3[digit*3+1]);
lcd.write(bn3[digit*3+2]);
}
// ===================================================================
void printTwoNumber(uint8_t number, uint8_t position)//13
{
// Print position is hardcoded
int digit0; // To represent the ones
int digit1; // To represent the tens
digit0=number%10;
digit1=number/10;

// Line 1 of the two-digit number
lcd.setCursor(position,0);
lcd.write(bn1[digit1*3]);
lcd.write(bn1[digit1*3+1]);
lcd.write(bn1[digit1*3+2]);
lcd.write(B); // Blank
lcd.write(bn1[digit0*3]);
lcd.write(bn1[digit0*3+1]);
lcd.write(bn1[digit0*3+2]);

// Line 2 of the two-digit number
lcd.setCursor(position,1);
lcd.write(bn2[digit1*3]);
lcd.write(bn2[digit1*3+1]);
lcd.write(bn2[digit1*3+2]);
lcd.write(B); // Blank
lcd.write(bn2[digit0*3]);
lcd.write(bn2[digit0*3+1]);
lcd.write(bn2[digit0*3+2]);

// Line 3 of the two-digit number
lcd.setCursor(position,2);
lcd.write(bn3[digit1*3]);
lcd.write(bn3[digit1*3+1]);
lcd.write(bn3[digit1*3+2]);
lcd.write(B); // Blank
lcd.write(bn3[digit0*3]);
lcd.write(bn3[digit0*3+1]);
lcd.write(bn3[digit0*3+2]);
}
// ===================================================================
void printDot(uint8_t position)
{
lcd.setCursor(position, 2);
lcd.write (3);
}
// ===================================================================
void printColons(uint8_t position)
{
lcd.setCursor(position, 0);
lcd.write (3);
lcd.setCursor(position, 2);
lcd.write (6);
}
// ===================================================================
void printNoColons(uint8_t position)
{
lcd.setCursor(position, 0);
lcd.write (B);
lcd.setCursor(position, 2);
lcd.write (B);
}
// ===================================================================
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
MenuItem menu_initial = MenuItem(“SHOW”);
MenuItem menu_1 = MenuItem(“SET TIME”);
MenuItem menu_2 = MenuItem(“SET DATE”);
MenuItem menu_3 = MenuItem(“SET ALARM”);

// ===================================================================
void menuUsed(MenuUseEvent used)
{
lcd.clear();
MenuItem (used.item.getName());//back to Main
// menu.toRoot();
MenuItem &getRoot();
}
// ===================================================================
void menuChanged(MenuChangeEvent changed)
{
int i;
int cursorPosition;

MenuItem newMenuItem=changed.to; //get the destination menu
// ===================================================================
// ===================================================================
if(newMenuItem.getName()==menu.getRoot())
{
lcd.clear();
splashScreen();
}
// ===================================================================
else if(newMenuItem.getName()==”SHOW”)
{
lcd.clear();
messageScreen();
}
// ===================================================================
else if(newMenuItem.getName()==”SET TIME”)//
{
getDateM41T80();
if(BUTTON == SELECT)
{
lcd.clear();
lcd.print(“1. SET TIME “);
delay(DELAY_2);
lcd.clear();
displayTime(6,Row1);
cursorPosition = 7;
lcd.setCursor(cursorPosition,1);
lcd.blink();
do
{
if(BUTTON == RIGHT)
{
BUTTON = NONE;
cursorPosition++;
if(cursorPosition == 14) cursorPosition = 7;
if(cursorPosition == 11) cursorPosition = 13;
if(cursorPosition == 8) cursorPosition = 10;
lcd.setCursor(cursorPosition,1);
beepBuzzer(1150,20);
}
if(BUTTON == LEFT)
{
BUTTON = NONE;
cursorPosition–;
if(cursorPosition == 6) cursorPosition = 13;
if(cursorPosition == 12) cursorPosition = 10;
if(cursorPosition == 9) cursorPosition = 7;
lcd.setCursor(cursorPosition,1);
beepBuzzer(1150,20);
}
if((BUTTON == UP) && (cursorPosition == 7))
{
BUTTON = NONE;
hourBuffer = hour;
hourBuffer++;
beepBuzzer(1150,20);
if(hourBuffer > 23) hourBuffer = 0;
if(hourBuffer < 10)
{
lcd.setCursor(cursorPosition-1,1); //7
lcd.print(“0”);
}
lcd.print(hourBuffer,DEC);
lcd.setCursor(7,1); //7
if(hourBuffer > 9)
{
lcd.setCursor(6,1); //6
lcd.print(hourBuffer,DEC);
lcd.print(“:”);
lcd.setCursor(7,1);
}
hour = hourBuffer;
}

if((BUTTON == UP) && (cursorPosition == 10))
{
BUTTON = NONE;
minuteBuffer = minute;
minuteBuffer++;
beepBuzzer(1150,20);
if(minuteBuffer > 59) minuteBuffer = 0;
if(minuteBuffer < 10)
{
lcd.setCursor(cursorPosition-1,1); //7
lcd.print(“0”);
}
lcd.print(minuteBuffer,DEC);
lcd.setCursor(10,1); //10
if(minuteBuffer > 9)
{
lcd.setCursor(9,1); //9
lcd.print(minuteBuffer,DEC);
lcd.print(“:”);
lcd.setCursor(10,1);
}
minute = minuteBuffer;
}

if((BUTTON == UP) && (cursorPosition == 13))
{
BUTTON = NONE;
secondBuffer = second;
secondBuffer++;
beepBuzzer(1150,20);
if(secondBuffer > 59) secondBuffer = 0;
if(secondBuffer < 10)
{
lcd.setCursor(cursorPosition-1,1); //7
lcd.print(“0″);
}
lcd.print(secondBuffer,DEC);
lcd.setCursor(13,1); //10
if(secondBuffer > 9)
{
lcd.setCursor(12,1); //9
lcd.print(secondBuffer,DEC);
lcd.print(” “);
lcd.setCursor(13,1);
}
second = secondBuffer;
}
// ===================================================================
if((BUTTON == DOWN) && (cursorPosition == 7))
{
BUTTON = NONE;
hourBuffer = hour;
hourBuffer–;
beepBuzzer(1150,20);
if(hourBuffer <= 0) hourBuffer = 23;
if(hourBuffer < 10)
{
lcd.setCursor(cursorPosition-1,1); //7
lcd.print(“0”);
}
lcd.print(hourBuffer,DEC);
lcd.setCursor(7,1); //7
if(hourBuffer > 9)
{
lcd.setCursor(6,1); //6
lcd.print(hourBuffer,DEC);
lcd.print(“:”);
lcd.setCursor(7,1);
}
hour = hourBuffer;
}

if((BUTTON == DOWN) && (cursorPosition == 10))
{
BUTTON = NONE;
minuteBuffer = minute;
minuteBuffer–;
beepBuzzer(1150,20);
if(minuteBuffer <= 0) minuteBuffer = 59;
if(minuteBuffer < 10)
{
lcd.setCursor(cursorPosition-1,1); //7
lcd.print(“0”);
}
lcd.print(minuteBuffer,DEC);
lcd.setCursor(10,1); //10
if(minuteBuffer > 9)
{
lcd.setCursor(9,1); //9
lcd.print(minuteBuffer,DEC);
lcd.print(“:”);
lcd.setCursor(10,1);
}
minute = minuteBuffer;
}

if((BUTTON == DOWN) && (cursorPosition == 13))
{
BUTTON = NONE;
secondBuffer = second;
secondBuffer–;
beepBuzzer(1150,20);
if(secondBuffer <= 0) secondBuffer = 59;
if(secondBuffer < 10)
{
lcd.setCursor(cursorPosition-1,1); //7
lcd.print(“0″);
}
lcd.print(secondBuffer,DEC);
lcd.setCursor(13,1); //10
if(secondBuffer > 9)
{
lcd.setCursor(12,1); //9
lcd.print(secondBuffer,DEC);
lcd.print(” “);
lcd.setCursor(13,1);
}
second = secondBuffer;
}

}
while(BUTTON != SELECT);
BUTTON = NONE;
// ===================================================================
setHourM41T80();
beepBuzzer(1150,20);
lcd.noBlink();
lcd.clear();
lcd.print(” HOUR IS SET! “);
delay(DELAY_2);
lcd.clear();
lcd.print(“1. SET TIME “);
delay(DELAY_1);
}
}
// ===================================================================
// ===================================================================
else if(newMenuItem.getName()==”SET DATE”)
{
getDateM41T80();
dayOfWeekBuffer = dayOfWeek;
dateBuffer = dayOfMonth;
monthBuffer = month;
yearBuffer = year;
if(BUTTON == SELECT)
{
lcd.clear();
lcd.print(“2. SET DATE “);
delay(DELAY_2);
lcd.clear();
displayDate(2,Row1);
cursorPosition = 4;
lcd.setCursor(cursorPosition,1);
lcd.blink();
do
{
if(BUTTON == RIGHT)
{
BUTTON = NONE;
beepBuzzer(1150,20);
cursorPosition++;
if(cursorPosition == 5) cursorPosition = 7;
if(cursorPosition == 8) cursorPosition = 11;
if(cursorPosition == 12) cursorPosition = 16;
if(cursorPosition == 17) cursorPosition = 4;
lcd.setCursor(cursorPosition,1);
}
if(BUTTON == LEFT)
{
BUTTON = NONE;
beepBuzzer(1150,20);
cursorPosition–;
if(cursorPosition == 3) cursorPosition = 16;
if(cursorPosition == 15) cursorPosition = 11;
if(cursorPosition == 10) cursorPosition = 7;
if(cursorPosition == 6) cursorPosition = 4;
lcd.setCursor(cursorPosition,1);
}
if((BUTTON == UP) && (cursorPosition == 4))
{
BUTTON = NONE;
beepBuzzer(1150,20);
dayOfWeekBuffer++;
if(dayOfWeekBuffer > 6) dayOfWeekBuffer = 0;
dayOfWeek = dayOfWeekBuffer;
lcd.setCursor(2,1);
lcd.print(Day[dayOfWeek]);
lcd.setCursor(4,1);
}

if((BUTTON == UP) && (cursorPosition == 7))
{
BUTTON = NONE;
beepBuzzer(1150,20);
dateBuffer++;
if(dateBuffer > 31) dateBuffer = 1;
if(dateBuffer > 9)
{
lcd.setCursor(6,1);
lcd.print(dateBuffer,DEC);
}
if(dateBuffer < 10)
{
lcd.setCursor(6,1);
lcd.print(“0”);
lcd.print(dateBuffer,DEC);
}
lcd.setCursor(7,1);
}
dayOfMonth = dateBuffer;

if((BUTTON == UP) && (cursorPosition == 11))
{
BUTTON = NONE;
beepBuzzer(1150,20);
monthBuffer++;
if(monthBuffer > 11) monthBuffer = 0;
month = monthBuffer;
lcd.setCursor(9,1);
lcd.print(Mon[month]);
lcd.setCursor(11,1);
}

if((BUTTON == UP) && (cursorPosition == 16))
{
BUTTON = NONE;
beepBuzzer(1150,20);
yearBuffer++;
if(yearBuffer > 99) yearBuffer = 0;
if(yearBuffer < 10)
{
lcd.setCursor(15,1);
lcd.print(“0”);
lcd.print(yearBuffer,DEC);
}
else if(yearBuffer > 9)
{
lcd.setCursor(15,1);
lcd.print(yearBuffer,DEC);
}
lcd.setCursor(16,1);
}
year = yearBuffer;

if((BUTTON == DOWN) && (cursorPosition == 4))
{
BUTTON = NONE;
beepBuzzer(1150,20);
dayOfWeekBuffer–;
if(dayOfWeekBuffer < 0)
{
dayOfWeekBuffer = 6;
}
dayOfWeek = dayOfWeekBuffer;
lcd.setCursor(2,1);
lcd.print(Day[dayOfWeek]);
lcd.setCursor(4,1);
}

if((BUTTON == DOWN) && (cursorPosition == 7))
{
BUTTON = NONE;
beepBuzzer(1150,20);
dateBuffer–;
if(dateBuffer < 1)
{
dateBuffer = 31;
}
if(dateBuffer > 9)
{
lcd.setCursor(6,1);
lcd.print(dateBuffer,DEC);
}
if(dateBuffer < 10)
{
lcd.setCursor(6,1);
lcd.print(“0”);
lcd.print(dateBuffer,DEC);
}
lcd.setCursor(7,1);
}
dayOfMonth = dateBuffer;

if((BUTTON == DOWN) && (cursorPosition == 11))
{
BUTTON = NONE;
beepBuzzer(1150,20);
monthBuffer–;
if(monthBuffer < 0)
{
monthBuffer = 11;
}
month = monthBuffer;
lcd.setCursor(9,1);
lcd.print(Mon[month]);
lcd.setCursor(11,1);
}

if((BUTTON == DOWN) && (cursorPosition == 16))
{
BUTTON = NONE;
beepBuzzer(1150,20);
yearBuffer–;
if(yearBuffer < 0)
{
yearBuffer = 99;
}
if(yearBuffer < 10)
{
lcd.setCursor(15,1);
lcd.print(“0″);
lcd.print(yearBuffer,DEC);
}
else if(yearBuffer > 9)
{
lcd.setCursor(15,1);
lcd.print(yearBuffer,DEC);
}
lcd.setCursor(16,1);
}
year = yearBuffer;

}
while(BUTTON != SELECT);

setDateM41T80();
lcd.noBlink();
beepBuzzer(1150,20);
lcd.clear();
lcd.print(” DATE IS SET! “);
delay(DELAY_2);
lcd.clear();
lcd.print(“2. SET DATE “);
delay(DELAY_1);
}
}
// ===================================================================
// ===================================================================
else if(newMenuItem.getName()==”SET ALARM”)
{
int setFlag;

if(BUTTON == SELECT)
{
initial = 0;
alarmHourBuffer = EEPROM.read(ALARM_HOUR_EEPROM_ADDRESS);
alarmMinuteBuffer = EEPROM.read(ALARM_MINUTE_EEPROM_ADDRESS);
buildFlags = EEPROM.read(ALARM_FLAG_EEPROM_ADDRESS);
if(alarmHourBuffer == 255) alarmHourBuffer = 0;
if(alarmMinuteBuffer == 255) alarmMinuteBuffer = 0;
if(buildFlags == B1111111) buildFlags = B11111110;

lcd.clear();
lcd.print(“3. SET ALARM “);
delay(DELAY_2);
lcd.clear();
lcd.write(SET);
lcd.print(“=SET”);
lcd.setCursor(13,0);
lcd.write(RESET);
lcd.print(“=RESET”);
displayAlarmTime(7,Row0);
lcd.setCursor(0,2);
lcd.print(“MO TU WE TH FR SA SU”);

lcd.setCursor(0,3);
if((buildFlags & B10000000)==B10000000) {
lcd.write(SET);
FLAGS.MONDAY_ALARM_FLAG = 1;
}
else {
lcd.write(RESET);
FLAGS.MONDAY_ALARM_FLAG = 0;
}
lcd.setCursor(3,3);
if((buildFlags & B01000000)==B01000000) {
lcd.write(SET);
FLAGS.TUESDAY_ALARM_FLAG = 1;
}
else {
lcd.write(RESET);
FLAGS.TUESDAY_ALARM_FLAG = 0;
}
lcd.setCursor(6,3);
if((buildFlags & B00100000)==B00100000) {
lcd.write(SET);
FLAGS.WEDNESDAY_ALARM_FLAG = 1;
}
else {
lcd.write(RESET);
FLAGS.WEDNESDAY_ALARM_FLAG = 0;
}
lcd.setCursor(9,3);
if((buildFlags & B00010000)==B00010000) {
lcd.write(SET);
FLAGS.THURSDAY_ALARM_FLAG = 1;
}
else {
lcd.write(RESET);
FLAGS.THURSDAY_ALARM_FLAG = 0;
}
lcd.setCursor(12,3);
if((buildFlags & B00001000)==B00001000) {
lcd.write(SET);
FLAGS.FRIDAY_ALARM_FLAG = 1;
}
else {
lcd.write(RESET);
FLAGS.FRIDAY_ALARM_FLAG = 0;
}
lcd.setCursor(15,3);
if((buildFlags & B00000100)==B00000100) {
lcd.write(SET);
FLAGS.SATURDAY_ALARM_FLAG = 1;
}
else {
lcd.write(RESET);
FLAGS.SATURDAY_ALARM_FLAG = 0;
}
lcd.setCursor(18,3);
if((buildFlags & B00000010)==B00000010) {
lcd.write(SET);
FLAGS.SUNDAY_ALARM_FLAG = 1;
}
else {
lcd.write(RESET);
FLAGS.SUNDAY_ALARM_FLAG = 0;
}

cursorPosition = 8;
lcd.setCursor(cursorPosition,0);
lcd.blink();
do
{
if(BUTTON == RIGHT)
{
BUTTON = NONE;
beepBuzzer(1150,20);
delay(250);
cursorPosition++;
if(cursorPosition == 9) cursorPosition = 11;
if(cursorPosition == 12) cursorPosition = 8;
lcd.setCursor(cursorPosition,0);
}
if(BUTTON == LEFT)
{
BUTTON = NONE;
beepBuzzer(1150,20);
delay(250);
cursorPosition–;
if(cursorPosition == 7) cursorPosition = 11;
if(cursorPosition == 10) cursorPosition = 8;
lcd.setCursor(cursorPosition,0);
}
if((BUTTON == UP) && (cursorPosition == 8))
{
BUTTON = NONE;
alarmHourBuffer++;
beepBuzzer(1150,20);
if(alarmHourBuffer > 23) alarmHourBuffer = 0;
if(alarmHourBuffer < 10)
{
lcd.setCursor(cursorPosition-1,0); //7
lcd.print(“0”);
}
lcd.print(alarmHourBuffer,DEC);
lcd.setCursor(8,0); //7
if(alarmHourBuffer > 9)
{
lcd.setCursor(7,0); //6
lcd.print(alarmHourBuffer,DEC);
lcd.print(“:”);
lcd.setCursor(8,0);
}
alarmHour = alarmHourBuffer;
}
if((BUTTON == UP) && (cursorPosition == 11))
{
BUTTON = NONE;
alarmMinuteBuffer++;
beepBuzzer(1150,20);
if(alarmMinuteBuffer > 59) alarmMinuteBuffer = 0;
if(alarmMinuteBuffer < 10)
{
lcd.setCursor(cursorPosition-1,0);
lcd.print(“0″);
}
lcd.print(alarmMinuteBuffer,DEC);
lcd.setCursor(11,0); //7
if(alarmMinuteBuffer > 9)
{
lcd.setCursor(10,0); //6
lcd.print(alarmMinuteBuffer,DEC);
lcd.print(” “);
lcd.setCursor(11,0);
}
alarmMinute = alarmMinuteBuffer;
}
if((BUTTON == DOWN) && (cursorPosition == 8))
{
BUTTON = NONE;
alarmHourBuffer–;
beepBuzzer(1150,20);
if(alarmHourBuffer < 0) alarmHourBuffer = 23;
if(alarmHourBuffer < 10)
{
lcd.setCursor(cursorPosition-1,0); //7
lcd.print(“0”);
}
lcd.print(alarmHourBuffer,DEC);
lcd.setCursor(8,0); //7
if(alarmHourBuffer > 9)
{
lcd.setCursor(7,0); //6
lcd.print(alarmHourBuffer,DEC);
lcd.print(“:”);
lcd.setCursor(8,0);
}
alarmHour = alarmHourBuffer;
}
if((BUTTON == DOWN) && (cursorPosition == 11))
{
BUTTON = NONE;
alarmMinuteBuffer–;
beepBuzzer(1150,20);
if(alarmMinuteBuffer < 0) alarmMinuteBuffer = 59;
if(alarmMinuteBuffer < 10)
{
lcd.setCursor(cursorPosition-1,0);
lcd.print(“0″);
}
lcd.print(alarmMinuteBuffer,DEC);
lcd.setCursor(11,0); //7
if(alarmMinuteBuffer > 9)
{
lcd.setCursor(10,0); //6
lcd.print(alarmMinuteBuffer,DEC);
lcd.print(” “);
lcd.setCursor(11,0);
}
alarmMinute = alarmMinuteBuffer;
}
}
while(BUTTON != SELECT);

beepBuzzer(1150,20);
delay(DELAY_1);
lcd.setCursor(4,1);
lcd.print(“ENABLE?”);
lcd.setCursor(12,1);
lcd.print(“YES “);

//=========================================================================DEBUG DEBUG DEBUG
// lcd.setCursor(0,1);
// lcd.print(buildFlags,BIN);
//=========================================================================DEBUG DEBUG DEBUG
while(BUTTON != SELECT)
{
lcd.setCursor(12,1);
lcd.blink();
if(BUTTON == RIGHT)
{
BUTTON = NONE;
beepBuzzer(1150,20);
lcd.setCursor(12,1);
lcd.print(“YES”);
alarmFlag = true;
i = 1;
delay(DELAY_1);
cursorPosition = 12;
}
if(BUTTON == LEFT)
{
BUTTON = NONE;
beepBuzzer(1150,20);
lcd.setCursor(12,1);
lcd.print(“NO “);
alarmFlag = false;
i = 0;
delay(DELAY_1);
cursorPosition = 12;
}
cursorPosition = 0;
}
lcd.setCursor(cursorPosition,3);
beepBuzzer(1150,20);
if(BUTTON == SELECT)
{
BUTTON = NONE;
delay(500);
do
{
BUTTON = NONE;
delay(500);
if(BUTTON == RIGHT)
{
boolean s;
int counter;

if(counter > 6) counter = 0;
switch(counter)
{
case 0:
lcd.setCursor(0,3);
break;
case 1:
lcd.setCursor(3,3);
break;
case 2:
lcd.setCursor(6,3);
break;
case 3:
lcd.setCursor(9,3);
break;
case 4:
lcd.setCursor(12,3);
break;
case 5:
lcd.setCursor(15,3);
break;
case 6:
lcd.setCursor(18,3);
break;
}

BUTTON = NONE;
beepBuzzer(1150,20);
delay(DELAY_1);

switch(counter)
{
BUTTON = NONE;
case 0:
counter++;
while(BUTTON != RIGHT)
{
delay(500);
if(BUTTON == SELECT)
{
beepBuzzer(1150,20);
if(FLAGS.MONDAY_ALARM_FLAG == 0) {
FLAGS.MONDAY_ALARM_FLAG = 1;
lcd.setCursor(0,3);
lcd.write(SET);
lcd.setCursor(0,3);
buildFlags = (buildFlags | 0x00);
}
else if(FLAGS.MONDAY_ALARM_FLAG == 1) {
FLAGS.MONDAY_ALARM_FLAG = 0;
lcd.setCursor(0,3);
lcd.write(RESET);
lcd.setCursor(0,3);
buildFlags = (buildFlags ^ B10000000);
}
BUTTON = NONE;
delay(500);
}
}
break;
case 1:
counter++;
while(BUTTON != RIGHT)
{
delay(500);
if(BUTTON == SELECT)
{
beepBuzzer(1150,20);
if(FLAGS.TUESDAY_ALARM_FLAG == 0) {
FLAGS.TUESDAY_ALARM_FLAG = 1;
lcd.setCursor(3,3);
lcd.write(SET);
lcd.setCursor(3,3);
buildFlags = (buildFlags | 0x00);
}
else if(FLAGS.TUESDAY_ALARM_FLAG == 1) {
FLAGS.TUESDAY_ALARM_FLAG = 0;
lcd.setCursor(3,3);
lcd.write(RESET);
lcd.setCursor(3,3);
buildFlags = (buildFlags ^ B01000000);
}
BUTTON = NONE;
delay(500);
}
}
break;
case 2:
counter++;
while(BUTTON != RIGHT)
{
delay(500);
if(BUTTON == SELECT)
{
beepBuzzer(1150,20);
if(FLAGS.WEDNESDAY_ALARM_FLAG == 0) {
FLAGS.WEDNESDAY_ALARM_FLAG = 1;
lcd.setCursor(6,3);
lcd.write(SET);
lcd.setCursor(6,3);
buildFlags = (buildFlags | 0x00);
}
else if(FLAGS.WEDNESDAY_ALARM_FLAG == 1) {
FLAGS.WEDNESDAY_ALARM_FLAG = 0;
lcd.setCursor(6,3);
lcd.write(RESET);
lcd.setCursor(6,3);
buildFlags = (buildFlags ^ B00100000);
}
BUTTON = NONE;
delay(500);
}
}
break;
case 3:
counter++;
while(BUTTON != RIGHT)
{
delay(500);
if(BUTTON == SELECT)
{
beepBuzzer(1150,20);
if(FLAGS.THURSDAY_ALARM_FLAG == 0) {
FLAGS.THURSDAY_ALARM_FLAG = 1;
lcd.setCursor(9,3);
lcd.write(SET);
lcd.setCursor(9,3);
buildFlags = (buildFlags | 0x00);
}
else if(FLAGS.THURSDAY_ALARM_FLAG == 1) {
FLAGS.THURSDAY_ALARM_FLAG = 0;
lcd.setCursor(9,3);
lcd.write(RESET);
lcd.setCursor(9,3);
buildFlags = (buildFlags ^ B00010000);
}
BUTTON = NONE;
delay(500);
}
}
break;
case 4:
counter++;
while(BUTTON != RIGHT)
{
delay(500);
if(BUTTON == SELECT)
{
beepBuzzer(1150,20);
if(FLAGS.FRIDAY_ALARM_FLAG == 0) {
FLAGS.FRIDAY_ALARM_FLAG = 1;
lcd.setCursor(12,3);
lcd.write(SET);
lcd.setCursor(12,3);
buildFlags = (buildFlags | 0x00);
}
else if(FLAGS.FRIDAY_ALARM_FLAG == 1) {
FLAGS.FRIDAY_ALARM_FLAG = 0;
lcd.setCursor(12,3);
lcd.write(RESET);
lcd.setCursor(12,3);
buildFlags = (buildFlags ^ B00001000);
}
BUTTON = NONE;
delay(500);
}
}
break;
case 5:
counter++;
while(BUTTON != RIGHT)
{
delay(500);
if(BUTTON == SELECT)
{
beepBuzzer(1150,20);
if(FLAGS.SATURDAY_ALARM_FLAG == 0) {
FLAGS.SATURDAY_ALARM_FLAG = 1;
lcd.setCursor(15,3);
lcd.write(SET);
lcd.setCursor(15,3);
buildFlags = (buildFlags | 0x00);
}
else if(FLAGS.SATURDAY_ALARM_FLAG == 1) {
FLAGS.SATURDAY_ALARM_FLAG = 0;
lcd.setCursor(15,3);
lcd.write(RESET);
lcd.setCursor(15,3);
buildFlags = (buildFlags ^ B00000100);
}
BUTTON = NONE;
delay(500);
}
}
break;
case 6:
counter++;
while(BUTTON != RIGHT)
{
delay(500);
if(BUTTON == SELECT)
{
beepBuzzer(1150,20);
if(FLAGS.SUNDAY_ALARM_FLAG == 0) {
FLAGS.SUNDAY_ALARM_FLAG = 1;
lcd.setCursor(18,3);
lcd.write(SET);
lcd.setCursor(18,3);
buildFlags = (buildFlags | 0x00);
}
else if(FLAGS.SUNDAY_ALARM_FLAG == 1) {
FLAGS.SUNDAY_ALARM_FLAG = 0;
lcd.setCursor(18,3);
lcd.write(RESET);
lcd.setCursor(18,3);
buildFlags = (buildFlags ^ B00000010);
}
BUTTON = NONE;
delay(500);
}
}
break;
}
delay(500);
}
}
while(BUTTON != SELECT);
}
lcd.noBlink();
alarmHour = alarmHourBuffer;
alarmMinute = alarmMinuteBuffer;
//===================================================DEBUG DEBUG DEBUG
// lcd.setCursor(0,2);
// lcd.print(buildFlags,BIN);
//===================================================DEBUG DEBUG DEBUG

EEPROM.write(ALARM_HOUR_EEPROM_ADDRESS, alarmHour);
EEPROM.write(ALARM_MINUTE_EEPROM_ADDRESS, alarmMinute);
EEPROM.write(ALARM_FLAG_EEPROM_ADDRESS, buildFlags);
beepBuzzer(1150,20);
lcd.clear();
lcd.print(” ALARM IS SET! “);
delay(DELAY_2);
lcd.clear();
lcd.print(“3. SET ALARM “);
delay(DELAY_1);
}
}
}
/*
boolean MONDAY_ALARM_FLAG : 1;
boolean TUESDAY_ALARM_FLAG : 1;
boolean WEDNESDAY_ALARM_FLAG : 1;
boolean THURSDAY_ALARM_FLAG : 1;
boolean FRIDAY_ALARM_FLAG : 1;
boolean SATURDAY_ALARM_FLAG : 1;
boolean SUNDAY_ALARM_FLAG : 1;
*/
// ===================================================================
void checkAlarm()
{
int i;
getDateM41T80();
i = EEPROM.read(ALARM_FLAG_EEPROM_ADDRESS);
if((alarmHour == hour) && (alarmMinute == minute) && (alarmFlag == true))// && ((FLAGS.MONDAY_ALARM_FLAG)|(FLAGS.TUESDAY_ALARM_FLAG)|(FLAGS.WEDNESDAY_ALARM_FLAG)|(FLAGS.THURSDAY_ALARM_FLAG)|(FLAGS.FRIDAY_ALARM_FLAG)|(FLAGS.SATURDAY_ALARM_FLAG)|(FLAGS.SUNDAY_ALARM_FLAG)))
{
if(FLAGS.MONDAY_ALARM_FLAG==1) quadBuzzer();
else if(FLAGS.TUESDAY_ALARM_FLAG==1) quadBuzzer();
else if(FLAGS.WEDNESDAY_ALARM_FLAG==1) quadBuzzer();
else if(FLAGS.THURSDAY_ALARM_FLAG==1) quadBuzzer();
else if(FLAGS.FRIDAY_ALARM_FLAG==1) quadBuzzer();
else if(FLAGS.SATURDAY_ALARM_FLAG==1) quadBuzzer();
else if(FLAGS.SUNDAY_ALARM_FLAG==1) quadBuzzer();
else {};
}
if(BUTTON == SELECT)
{
alarmFlag = false;
}
}
// ===================================================================
void quadBuzzer()
{
beepBuzzer(3150,80);
delay(50);
beepBuzzer(3150,80);
delay(50);
beepBuzzer(3150,80);
delay(50);
beepBuzzer(3150,80);
delay(50);
beepBuzzer(3150,80);
delay(500);
}
// ===================================================================
void setup()
{
int i;

Wire.begin();
lcd.begin(20, 4);

DefineLargeChar(); // Create the custom characters
lcd.clear();
delay(20);
pinMode(BUZZER_PIN, OUTPUT);

#if defined(__AVR_ATmega644P__)
pinMode(BACKLIT_PIN, OUTPUT);
digitalWrite(BACKLIT_PIN,HIGH);
#endif

Timer1.initialize(300000); //
Timer1.attachInterrupt( timer1Isr ); // attach the service routine here
MsTimer2::set(1000, timer2Isr); // 500ms period
MsTimer2::start();
// ===================================================================
//configure menu
menu.getRoot().add(menu_initial);
menu_initial.add(menu_1);
menu_1.add(menu_2);
menu_2.add(menu_3);
menu.toRoot();
lcd.clear();
splashScreen();
alarmHour = EEPROM.read(ALARM_HOUR_EEPROM_ADDRESS);
alarmMinute = EEPROM.read(ALARM_MINUTE_EEPROM_ADDRESS);
i = EEPROM.read(ALARM_FLAG_EEPROM_ADDRESS);
buildFlags = i;
if(i == 0x00) alarmFlag = false;
if(i == 0x01) alarmFlag = true;
}
// ===================================================================
void loop()
{
navigateMenus();
}
// ===================================================================
void measureTemperature()
{
Wire.beginTransmission(LM75_ADDRESS);
Wire.write(0x00);
Wire.requestFrom(LM75_ADDRESS, 2);
if (Wire.available())
{
int8_t msb = Wire.read();
int8_t lsb = Wire.read();
lsb = (lsb & 0x80 ) >> 7;
temperature = (msb + 0.5 * lsb)-3;
}
Wire.endTransmission();
farenheit = temperature*9/5+32;
}
// ===================================================================
void show()
{
if((second >= 5) && (second <= 10) || (second >= 30) && (second <= 35))
{
measureTemperature();
integerPart = (int)temperature;
decimalPart = ((int)(temperature*N_DECIMAL_POINTS_PRECISION)%N_DECIMAL_POINTS_PRECISION);
lcd.clear();
printTwoNumber(integerPart,1);
printDot(9);
lcd.setCursor(16,0);
lcd.print(“O”);
printOneNumber(decimalPart,11);
printOneLetter(C_,17);
}
else
{
lcd.clear();
printTwoNumber(hour,1);
printTwoNumber(minute,11);

unsigned long currentMillis = millis();
if(currentMillis – previousMillis > interval)
{
previousMillis = currentMillis;
colonFlag = !colonFlag;
}
if(colonFlag == false) printColons(9);
else if(colonFlag == true) printNoColons(9);
if(hour < 12)
{
lcd.setCursor(19,0);
lcd.print(“A”);
lcd.setCursor(19,1);
lcd.print(“M”);
}
else if(hour >= 12)
{
lcd.setCursor(19,0);
lcd.print(“P”);
lcd.setCursor(19,1);
lcd.print(“M”);
}
//DEBUG

//DEBUG
}
}
// ===================================================================
void printFloat(float value, int places)
{
int digit;
float tens = 0.1;
int tenscount = 0;
int i;
float tempfloat = value;
float d = 0.5;

if (value < 0) d *= -1.0;
for (i = 0; i < places; i++) d/= 10.0;
tempfloat += d;
if (value < 0) tempfloat *= -1.0;
while ((tens * 10.0) <= tempfloat)
{
tens *= 10.0;
tenscount += 1;
}
if (value < 0) lcd.print(‘-‘);
if (tenscount == 0) lcd.print(0, DEC);
for (i=0; i< tenscount; i++)
{
digit = (int) (tempfloat/tens);
lcd.print(digit, DEC);
tempfloat = tempfloat – ((float)digit * tens);
tens /= 10.0;
}
if (places <= 0) return;
lcd.print(‘.’);
for (i = 0; i < places; i++)
{
tempfloat *= 10.0;
digit = (int) tempfloat;
lcd.print(digit,DEC);
tempfloat = tempfloat – (float) digit;
}
}
// ==================================================================================
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// ==================================================================================
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// ==================================================================================
void setDateM41T80() // 0-99
{
Wire.beginTransmission(M41T80_I2C_ADDRESS);
Wire.write(0x04);
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
// ==================================================================================
void setHourM41T80() // 0-99
{
Wire.beginTransmission(M41T80_I2C_ADDRESS);
Wire.write(0x00);
Wire.write(decToBcd(msecond));
Wire.write(decToBcd(second) & 0x7F); // 0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour)); // If you want 12 hour am/pm you need to set
Wire.endTransmission();
}
// ==================================================================================
void getDateM41T80()
{
Wire.beginTransmission(M41T80_I2C_ADDRESS);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(M41T80_I2C_ADDRESS, 8);
msecond = bcdToDec(Wire.read());
second = bcdToDec(Wire.read() & 0x7f);
minute = bcdToDec(Wire.read());
hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm
dayOfWeek = bcdToDec(Wire.read());
dayOfMonth = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = bcdToDec(Wire.read());
Wire.endTransmission();
}
// ===================================================================
void timer1Isr()
{
Buttons.loopCheck();
readButtons(BUTTON);
}
// ===================================================================
void timer2Isr()
{

}
// ===================================================================
void readButtons(byte i)
{
if(i == 255) BUTTON = 0;
else BUTTON = i;
}
// ===================================================================
void beepBuzzer(unsigned long hz, unsigned long ms)
{
unsigned long us = (750000 / hz);
unsigned long rep = (ms * 500L) / us;

for (int i = 0; i < rep; i++)
{
digitalWrite(BUZZER_PIN, HIGH);
delayMicroseconds(us);
digitalWrite(BUZZER_PIN, LOW);
delayMicroseconds(us);
}
}
// ===================================================================
void messageScreen()
{
int space = 4;
lcd.clear();
printOneLetter(A_,0);
printOneLetter(R_,space);
printOneLetter(D_,2*space);
printOneLetter(U_,3*space);
lcd.setCursor(15,2);
lcd.print(“CLOCK”);
lcd.setCursor(16,3);
lcd.print(“V1.0”);
}
// ===================================================================
void splashScreen()
{
repeatScroll();
getDateM41T80();
show();
displayTime(0, Row3);
displayDate(9, Row3);
}
// ===================================================================
void navigateMenus()
{
MenuItem currentMenu = menu.getCurrent();
Button = BUTTON;
switch (BUTTON)
{
case SELECT:
beepBuzzer(1150,20);
if(!(currentMenu.moveDown()))
{
menu.use();
}
else
{
menu.moveDown();
}
break;
case ESCAPE:
beepBuzzer(1150,20);
menu.toRoot();
break;
case RIGHT:
beepBuzzer(1150,20);
menu.moveRight();
break;
case LEFT:
beepBuzzer(1150,20);
menu.moveLeft();
break;
case UP:
beepBuzzer(1150,20);
menu.moveUp();
break;
case DOWN:
beepBuzzer(1150,20);
menu.moveDown();
break;
}
BUTTON = NONE;
}
// ===================================================================
void displayAlarm(int col, int row)
{
lcd.setCursor(col,row);

if (alarmHour < 10)
{
lcd.print(“0”);
}
lcd.print(alarmHour, DEC);
lcd.print(“:”);

if (alarmMinute < 10)
{
lcd.print(“0”);
}
lcd.print(alarmMinute, DEC);
}
// ===================================================================
void displayTime(int col, int row)
{
lcd.setCursor(col,row);

if (hour < 10)
{
lcd.print(“0”);
}
lcd.print(hour, DEC);
lcd.print(“:”);

if (minute < 10)
{
lcd.print(“0”);
}
lcd.print(minute, DEC);
lcd.print(“:”);

if (second < 10)
{
lcd.print(“0”);
}
lcd.print(second, DEC);
delay(500);
}
// ===================================================================
void displayAlarmTime(int col, int row)
{
lcd.setCursor(col,row);
if(alarmHour == 255) alarmHour = 0;
if(alarmMinute == 255) alarmMinute = 0;
if (alarmHour < 10)
{
lcd.print(“0”);
}
lcd.print(alarmHour, DEC);
lcd.print(“:”);

if (alarmMinute < 10)
{
lcd.print(“0″);
}
lcd.print(alarmMinute, DEC);
delay(500);
}
// ===================================================================
void displayDate(int col, int row)
{
lcd.setCursor(col,row);

lcd.print(Day[dayOfWeek]);

lcd.print(” “);

if(dayOfMonth < 10)
{
lcd.print(“0″);
}
lcd.print(dayOfMonth, DEC);
lcd.print(” “);
lcd.print(Mon[month]);
lcd.print(” 20″);

if (year < 10)
{
lcd.print(“0”);
}
lcd.print(year, DEC);
delay(500);
}
// ===================================================================
void concatenateData()
{
int i;
byte b;
byte mo, tu, we, th, fr, sa, su = 0;
buildFlags = EEPROM.read(ALARM_FLAG_EEPROM_ADDRESS);
//===================================================DEBUG DEBUG DEBUG
// lcd.setCursor(5,1);
// lcd.print(buildFlags,BIN);
//===================================================DEBUG DEBUG DEBUG

mo = (buildFlags & B10000000);
if(mo == B10000000) mo = 0;
else{
mo = 7;
}
tu = (buildFlags & B01000000);
if(tu == B01000000) tu = 1;
else{
tu = 7;
}
we = (buildFlags & B00100000);
if(we == B00100000) we = 2;
else{
we = 7;
}
th = (buildFlags & B00010000);
if(th == B00010000) th = 3;
else{
th = 7;
}
fr = (buildFlags & B00001000);
if(fr == B00001000) fr = 4;
else{
fr = 7;
}
sa = (buildFlags & B00000100);
if(sa == B00000100) sa = 5;
else{
sa = 7;
}
su = (buildFlags & B00000010);
if(su == B00000010) su = 6;
else{
su = 7;
}

memset(dataBuffer, ‘ ‘, (DATA_LENGTH-1));
snprintf(dataBuffer, (DATA_LENGTH-1), “ALARM SET AT: %02d:%02d, REPEAT: %02s %02s %02s %02s %02s %02s %02s “, alarmHour, alarmMinute, DAY[mo], DAY[tu], DAY[we], DAY[th], DAY[fr], DAY[sa], DAY[su]);
for(i = 0; i<3; i++)
{
dataBuffer[(DATA_LENGTH-2)+i] = ‘ ‘;
}
//===================================================DEBUG DEBUG DEBUG
// lcd.setCursor(5,0);
// lcd.print(buildFlags,BIN);
//===================================================DEBUG DEBUG DEBUG

}
// ===================================================================
void concatenate()
{
int i;

measureTemperature();
getDateM41T80();
memset(timeBuffer, ‘ ‘, (MESSAGE_LENGTH-1));
snprintf(timeBuffer, (MESSAGE_LENGTH-1), “%02d:%02d:%02d %s, %02d %s 20%02d %02d.%d\u00B2C “, hour, minute, second, Day[dayOfWeek], dayOfMonth, Mon[month], year, integerPart, decimalPart);
for(i = 0; i<3; i++)
{
timeBuffer[(MESSAGE_LENGTH-2)+i] = ‘ ‘;
}
}
// ===================================================================
void scrollDataDisplay(int line, int speed)
{
int i;

if(g_nPosition < DATA_LENGTH – DISPLAY_WIDTH)
{
for(i=0; i<DISPLAY_WIDTH; i++)
{
lcd.setCursor(i, line);
lcd.print(dataBuffer[g_nPosition + i]);
lcd.print(dataBuffer[56] = ‘ ‘);
}
}
else
{
int nChars = DATA_LENGTH – g_nPosition;
for(i=0; i<nChars; i++)
{
lcd.setCursor(i, line);
lcd.print(dataBuffer[g_nPosition + i]);
lcd.print(dataBuffer[56] = ‘ ‘);
}
for(i=0; i<(DISPLAY_WIDTH – nChars); i++)
{
lcd.setCursor(nChars + i, line);
lcd.print(dataBuffer[i]);
lcd.print(dataBuffer[56] = ‘ ‘);
}
}
g_nPosition++;
if(g_nPosition >= DATA_LENGTH)
{
g_nPosition = 0;
}
delay(speed);
}
// ===================================================================
void scrollDisplay(int line, int speed)
{
int i;

if(g_nPosition < MESSAGE_LENGTH – DISPLAY_WIDTH)
{
for(i=0; i<DISPLAY_WIDTH; i++)
{
lcd.setCursor(i, line);
lcd.print(timeBuffer[g_nPosition + i]);
lcd.print(timeBuffer[34] = ‘ ‘);
}
}
else
{
int nChars = MESSAGE_LENGTH – g_nPosition;
for(i=0; i<nChars; i++)
{
lcd.setCursor(i, line);
lcd.print(timeBuffer[g_nPosition + i]);
lcd.print(timeBuffer[34] = ‘ ‘);
}
for(i=0; i<(DISPLAY_WIDTH – nChars); i++)
{
lcd.setCursor(nChars + i, line);
lcd.print(timeBuffer[i]);
lcd.print(timeBuffer[34] = ‘ ‘);
}
}
g_nPosition++;
if(g_nPosition >= MESSAGE_LENGTH)
{
g_nPosition = 0;
}
delay(speed);
show();
}
// ===================================================================
void repeatScroll()
{
boolean hide = 0, noHide = 1;

readButtons(BUTTON);
do
{
if((hide == 0) && (noHide == 1))
{
concatenate();
scrollDisplay(3, 350);
}
if(alarmFlag == true)
{
lcd.setCursor(0,1);
lcd.print(“*”);//248
}
else if(alarmFlag == false)
{
lcd.setCursor(0,1);
lcd.write(32);
}
checkAlarm();
if(BUTTON == LEFT)
{
hide = 1;
noHide = 0;
lcd.clear();
printTwoNumber(alarmHour,1);
printColons(9);
printTwoNumber(alarmMinute,11);
if(alarmFlag == true)
{
lcd.setCursor(19,2);
lcd.print(“*”);
lcd.setCursor(19,0);
lcd.print(“A”);
lcd.setCursor(19,1);
lcd.print(“L”);
}
if(alarmFlag == false)
{
lcd.setCursor(19,2);
lcd.print(” “);
lcd.setCursor(19,0);
lcd.print(” “);
lcd.setCursor(19,1);
lcd.print(” “);
}
if((hide == 1) && (noHide == 0))
{
concatenateData();
scrollDataDisplay(3, 350);
}
}
if(BUTTON == RIGHT)
{
alarmFlag = !alarmFlag;
delay(500);
}
}
while(BUTTON != ESCAPE);

lcd.clear();
}
// ===================================================================

DIY SMD Soldering Station with AVR (MEGA2560 VERSION)

Free counters!

At the https://debugginglab.wordpress.com/2014/10/30/soldering-station/ from Matthias Wagner, I saw a DIY project of a soldering station with nice user interface and clever control of the RT series soldering tips of Weller. It was so interesting that I decided to make some changes on the hardware and of course re-writing of the firmware.

It is based on a ATMega644 controller, it has a 2.4″ TFT and a rotary encoder for the user interface and is designed to support two kinds of soldering irons: the classic RT tips or other devices with in-built heat sensor and the simple devices with only the heating element.

20151224_084414.jpg

The small 2.4″ TFT is on an Arduino MEGA1280 for developing of the initial code and making fine adjustments of the -on screen- details.

20151224_090330.jpg

The splash screen can be any 320×240 pixels .bmp file and can be processed in any image conversion program like Ms Paint.

My original thought was to use a simple, low power, cheap soldering iron for soldering up to 1206 dimension SMT parts, such as chip resistors and capacitors and small package IC’s. The problem with this is that since the soldering iron has no temperature sensing (RTD sensor, thermocouple sensor), it is very difficult to calculate the tip temperature of the device. I know though from Physics the relationship between the resistance and temperature of a resistor (i.e. the heating element itself), so with some effort I can take some feedback for an automated temperature controller.

Since the electrical resistance of a conductor such as a copper wire is dependent upon collisional processes within the wire, the resistance could be expected to increase with temperature since there will be more collisions. An intuitive approach to temperature dependence leads one to expect a fractional change in resistance which is proportional to the temperature change:

ΔR is the difference between initial and final (R resistance, T temperature) and α is the temperature co-efficient of a resistor or the material of the resistor (for my case, the heating element material is a Nickel-Chrome alloy, very common for soldering iron resistors).

So, the above formula can be more simple, solving for the unknown temperature. It is supposed that the every single moment heating element’s resistor value can be found from the moment current that leaks the element:

In the very useful page http://hyperphysics.phy-astr.gsu.edu/hbase/electric/restmp.html  can someone calculate the resistor’s temperature by inserting all other values in different fields. Very useful, indeed!

The main problem now is to make something that can measure very slight changes of iron’s resistor, such as from about 26 to 30 Ohms. These 4 Ohms have to be divided in about 375 parts, since the temperature of the tip is expected to reach the 400 degrees of Celsius centigrade. This means that if the nominal operating voltage of the iron is 12 volts, the current we have to measure varies from 12/26=0,4015 to  12/30=0,4000 Amperes. The accuracy range of the ADC must be then not less of a 0,00015075 Α  per one degree for a temperature range of ambient 25 to maximum 400 degrees.

To be honest, I would like to express my reservations on this approach but the magic of the unknown would not make no sense…

UPDATE (22 FEB 2016):

After some research, I realized that the above approach to this kind of design had very little chances to succeed. So I revised my design in order to fit it in market’s soldering iron types. The updated design has 3 options of tip temperature measurement, depending on the thermal sensor type of the soldering iron. PTC, NTC and K-TC sensors have been implemented and can be easily chosen through a quadruple DIP switch. The signal amplifiers are separate, each for every type, so defining the soldering tip’s sensor in the code, the program executes accordingly.

The core of the design depends now on a very interesting ΑΤMEGA2560 core I found:

s-l1600

http://www.ebay.com/itm/221502571388?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

DS-Mega2560-CORE-V01-EN datasheet

This one has plenty of flash memory, so I can do many things with graphics on the TFT.

3types

This part of the design shows the individual signal amplifying stages before the 10bit ADC measurement.

area1

area2.png

Continue reading DIY SMD Soldering Station with AVR (MEGA2560 VERSION)

This site is dedicated to the modern science of Digital Electronics