Letar efter demo kod för 8-bit mode LCD
Letar efter demo kod för 8-bit mode LCD
Jag får inte lcdn, (hd44780) att funka i 8 bitar mode med Arduino mega 1280
Det är väl förmodligen felkopplat någonstans gentemot koden.
Eller att den är trasig?
Lcdn går via en 74hc595n till Arduinon.
Provar jag i 4 bitar mode utan 74hc595n och annan kod så funkar det.
Så jag tänkte höra om någon har något kod exempel för 8 bit mode via en 74hc595n så jag kan försöka vidare?
Det är väl förmodligen felkopplat någonstans gentemot koden.
Eller att den är trasig?
Lcdn går via en 74hc595n till Arduinon.
Provar jag i 4 bitar mode utan 74hc595n och annan kod så funkar det.
Så jag tänkte höra om någon har något kod exempel för 8 bit mode via en 74hc595n så jag kan försöka vidare?
Re: Letar efter demo kod för 8 bit mode lcd.
Du kan ju börja med ett schema och lite relevant kod, så kanske....
Re: Letar efter demo kod för 8 bit mode lcd.
Jag tänkte lite generellt bara.
Men visst kan jag lägga upp det, strax.
Men visst kan jag lägga upp det, strax.
Re: Letar efter demo kod för 8 bit mode lcd.
Det är bara lcd, skift registret, och pulsgivaren (encoder) inkopplad.
EDIT> Programmet skapades för UNO versionen, schemat visar pinne 10 SS, 11 MOSI, 13 SCK
På mega 1280 sitter dom på 51, MOSI , 52 SCK, 53 SS
Det går att ladda upp utan problem men visar som sagt inget på lcd, har väl missat något dumt antar jag.
Här är källkod och bibliotek.
Jag kör i Arduino 00.23.
LiquidCrystal_SPI_8Bit biblioteket i sin helhet.
EDIT> Programmet skapades för UNO versionen, schemat visar pinne 10 SS, 11 MOSI, 13 SCK
På mega 1280 sitter dom på 51, MOSI , 52 SCK, 53 SS
Det går att ladda upp utan problem men visar som sagt inget på lcd, har väl missat något dumt antar jag.
Här är källkod och bibliotek.
Jag kör i Arduino 00.23.
Kod: Markera allt
#ifndef DOSE_head_h
#define DOSE_head_h
#include "WProgram.h"
#include "LiquidCrystal_SPI_8Bit.h"
#include "EEPROM.h"
#include "Time.h"
#include "DosingPump.h"
#include "QuickPin.h"
/******** EEPROM ADDRESSES ********/
#define EA_CALIBRATION_FLAGS 16
#define EA_ALK_PUMP 18
#define EA_CA_PUMP 28
#define EA_ALK_SCHEDULE 50
#define EA_CA_SCHEDULE 80
/*********** CONSTANTS ***********/
#define NUMBER_OF_PUMPS 2
#define DEBOUNCE 50
#define DEFAULT_VOLUME 20.0
#define DEFAULT_RATE 20.0
#define MIDNIGHT 1440
#define MAXIMUM_DAILY_VOLUME 120
#define MAXIMUM_CONTAINER_SIZE 5000
#define MAXIMUM_BOOSTER_DOSE 250
#define MAXIMUM_BOOSTER_DAYS 14
/*********** TYPEDEFS ***********/
typedef char* menu_t;
/*********** KNOBS AND BUTTONS *********/
QuickPin button1(7, INPUT, HIGH);
//QuickPin button2(2, INPUT, LOW); // second button unused
QuickPin encoder_Int_Pin(2, INPUT, HIGH);
QuickPin encoder_B_Pin(4, INPUT, HIGH);
char encoder_Counter; //Used to keep count of Rotary Encoder Clicks
/********** DISPLAY **********/
LiquidCrystal_SPI_8Bit LCD(8,10);
/********** PUMPS **********/
DosingPump AlkPump(5);
DosingPump CaPump(6);
/********** TIME **********/
time_t current_time;
/****** REPLACEMENT OPERATORS ******/
/*void* operator new(size_t size)
{
return malloc(size);
}
void operator delete(void* ptr)
{
free(ptr);
}
/********************* ENCODER FUNCTIONS *******************/
void ISR_encoder_handler()
{
(encoder_Int_Pin == encoder_B_Pin)? encoder_Counter++ : encoder_Counter--;
}
void encoderOn()
{
attachInterrupt(0, ISR_encoder_handler, FALLING); // Only using one edge and one interrupt so we get one increment per click
encoder_Counter = 0;
}
void encoderOff()
{
detachInterrupt(0);
encoder_Counter = 0;
}
char checkRotaryEncoder() // Used to get the value of encoder_Counter and reset it
{
char val = encoder_Counter;
encoder_Counter = 0;
return val;
}
template<class T>
void useRotaryEncoder(T& _var)
{
_var += checkRotaryEncoder();
}
template<class T>
void useRotaryEncoder(T& _var, int _mult)
{
_var += (checkRotaryEncoder() * _mult);
}
template<class T>
void useRotaryEncodersingle(T& _var)
{
int _val = checkRotaryEncoder();
if (_val > 0) _var += 1;
if (_val < 0) _var -= 1;
}
/***************** HUMAN INTERFACE INPUT FUNCTIONS ****************/
template<class T>
void printTheNumber(T& _var, int _digits, byte _col, byte _row)
{
// This function handles leading zeros
// In numbers that need them
// So our display stays straight
LCD.setCursor(_col, _row);
if (_var == 0)
{
for (int d_count = 0; d_count < _digits - 1; d_count ++)
{
LCD.print("0");
}
}
if ((_digits > 1) && (_var != 0))
{
int single_digit = (_var / (pow(10, (_digits - 1))));
if (single_digit == 0)
{
LCD.print("0");
printTheNumber(_var, (_digits -1) , _col +1, _row );
}
else
{
LCD.print(_var);
}
}
else
{
LCD.print(_var);
}
return; // when digits is equal to one, or we hit a digit other than 0 we fall through print and return
}
template<class T>
void inputTheNumber (T& _var, int _digits, int _min, int _max, byte _col, byte _row, int _mult)
{
LCD.cursor();
printTheNumber(_var, _digits, _col, _row);
while (button1==LOW); // if the button is still pressed, wait for release.
encoderOn();
do {
useRotaryEncoder(_var, _mult);
if (_var > _max) _var = _min;
if (_var < _min) _var = _max;
printTheNumber(_var, _digits, _col, _row);
LCD.setCursor(_col + (_digits -1), _row);
delay(100);
} while (button1==HIGH); // button press to end loop and lock in entry
while (button1==LOW); // wait for button release
encoderOff();
LCD.noCursor();
}
template<class T>
void inputTheNumber (T& _var, int _digits, int _min, int _max, byte _col, byte _row)
{
inputTheNumber(_var, _digits, _min, _max, _col, _row, 1);
}
template<class T>
void inputTheNumber (T& _var, int _digits, int _min, int _max, byte _col, byte _row, int _mult, char* _disp)
{
// Use whatever numbers you want for col and row, it doesn't matter
// They will be set to 0,1
LCD.clear();
LCD.print(_disp);
inputTheNumber(_var, _digits, _min, _max, 0, 1, _mult);
}
/****************** EEPROM FUNCTIONS *****************/
template<class T>
void writeToEEPROM(int address, T& value)
{
union {
T type;
byte b[sizeof(T)];
} temp;
temp.type = value;
for (int i = 0; i < sizeof(T); i++)
{
EEPROM.write(address + i, temp.b[i]);
}
}
template<class T>
void readFromEEPROM(int address, T& value)
{
union {
T type;
byte b[sizeof(T)];
} temp;
for (int i = 0; i < sizeof(T); i++)
{
temp.b[i] = EEPROM.read(address + i);
}
value = temp.type;
}
/*********************FUNCTION DECLARATIONS NOT IN OTHER HEADERS ***************/
void primePump(DosingPump* _pump);
void calibratePWM(DosingPump* _pump);
void calibrateMinFlow(DosingPump* _pump);
void calibrateMaxFlow(DosingPump* _pump);
void calibratePump(DosingPump* _pump);
void saveCalibration();
void getCalibration();
/**************** GENERAL FUNCTIONS and CALIBRATION *****************/
void primePump(DosingPump* _pump)
{
while(button1==LOW); // If button is pressed, wait until released
boolean quit = false;
encoderOn();
do
{
// turn knob to choose quit or prime
// press button to execute
if (checkRotaryEncoder() != 0) quit = !quit;
LCD.clear();
LCD.setCursor(0,1);
if (quit) LCD.print("QUIT ");
else LCD.print("PRIME");
delay(50); //display delay
if ((button1==LOW) && (quit == false)) // button press chose PRIME
{
encoderOff(); //turn off interrupt
(*_pump).pumpOn();
while (button1 == LOW); // run pump and wait until button release
(*_pump).pumpOff();
encoderOn();
}
}while((!quit) || (button1==HIGH)); // button press to exit only if QUIT
encoderOff();
}
void calibratePWM(DosingPump* _pump)
{
// Turn knob to adjust PWM rate until it you find the lowest setting
// that the pump can run at reliably. This will set your minimum
// flow rate
while(button1==LOW); // If button is pressed, wait for release
int pwm_rate = 128; // Start at 50% Most pumps won't run well below that
LCD.clear();
LCD.print("Adjust PWM");
encoderOn();
do
{
useRotaryEncoder(pwm_rate);
constrain(pwm_rate, 127, 255); // pwm stays between 50% and 100%
LCD.setCursor(0,1);
LCD.print(pwm_rate);
analogWrite((*_pump).pump_pin, pwm_rate);
} while(button1==HIGH); // button press to exit and lock in entry
analogWrite((*_pump).pump_pin, 0);
while(button1==LOW); // wait for button release
encoderOff();
(*_pump).minimum_pwm_rate = pwm_rate; // Set minimum PWM rate
}
void calibrateMinFlow(DosingPump* _pump)
{
// Button press to start. Pump will run for a pre-set time.
// Catch the flow, measure the amount, and input the amount after the pump
// stops running. This calculates the minimum flow rate.
int _volume = 0;
while(button1==LOW); // If button is pressed, wait for release
LCD.clear();
LCD.print("Press Button");
LCD.setCursor(0,1);
LCD.print("When Ready");
while(button1==HIGH); // wait for button press
LCD.clear();
LCD.print("Running...");
delay(1000);
while(button1==LOW); // wait for button release if it's not already.
long start_time = millis();
analogWrite((*_pump).pump_pin, (*_pump).minimum_pwm_rate);
while(millis() < (start_time + 30000)); // Wait for 30 seconds
analogWrite((*_pump).pump_pin, 0);
LCD.clear();
LCD.print("Enter Volume");
inputTheNumber(_volume, 2, 0, 99, 0, 1); // input the volume you got from the pump
(*_pump).minimum_flow_rate = (_volume * 2); // Convert and Record as mL per minute
}
void calibrateMaxFlow(DosingPump* _pump)
{
// Button press to start. Pump will run for a pre-set time.
// Capture the output, and input the amount after the pump
// stops running. This calculates the maximum flow rate.
int _volume = 0;
while(button1==LOW); // If button is pressed, wait for release
LCD.clear();
LCD.print("Press Button");
LCD.setCursor(0,1);
LCD.print("When Ready");
while(button1==HIGH); // Wait for button press
LCD.clear();
LCD.print("Running...");
delay(1000);
while(button1==LOW); // wait for button release if it's not already.
long start_time = millis();
analogWrite((*_pump).pump_pin, (*_pump).maximum_pwm_rate);
while(millis() < (start_time + 30000)); // wait 30 seconds
analogWrite((*_pump).pump_pin, 0);
LCD.clear();
LCD.print("Enter Volume");
inputTheNumber(_volume, 2, 0, 99, 0, 1); // input the volume you got from the pump
(*_pump).maximum_flow_rate = (_volume * 2); // Convert and record as ml / min
}
void calibratePump(DosingPump* _pump)
{
// Runs all the calibration methods
calibratePWM(_pump);
calibrateMinFlow(_pump);
calibrateMaxFlow(_pump);
}
void saveCalibration()
{
writeToEEPROM(EA_ALK_PUMP, AlkPump.minimum_pwm_rate);
writeToEEPROM(EA_ALK_PUMP + 2, AlkPump.minimum_flow_rate);
writeToEEPROM(EA_ALK_PUMP + 6, AlkPump.maximum_flow_rate);
writeToEEPROM(EA_CA_PUMP, CaPump.minimum_pwm_rate);
writeToEEPROM(EA_CA_PUMP + 2, CaPump.minimum_flow_rate);
writeToEEPROM(EA_CA_PUMP + 6, CaPump.maximum_flow_rate);
byte flag = 3;
writeToEEPROM(EA_CALIBRATION_FLAGS, flag);
}
void getCalibration()
{
readFromEEPROM(EA_ALK_PUMP, AlkPump.minimum_pwm_rate);
readFromEEPROM(EA_ALK_PUMP + 2, AlkPump.minimum_flow_rate);
readFromEEPROM(EA_ALK_PUMP + 6, AlkPump.maximum_flow_rate);
readFromEEPROM(EA_CA_PUMP, CaPump.minimum_pwm_rate);
readFromEEPROM(EA_CA_PUMP + 2, CaPump.minimum_flow_rate);
readFromEEPROM(EA_CA_PUMP + 6, CaPump.maximum_flow_rate);
}
/***************************************************
****** THESE HEADERS ARE SPECIFIC TO THIS**********
****** APPLICATION AND MUST REMAIN AT ************
******** THE END OF THIS FILE *************
**************************************************/
#include "DOSE_clock.h"
#include "DOSE_schedule.h"
Dose_S Alk_Schedule;
Dose_S Ca_Schedule;
// Schedule names and pointers to them.
Dose_S* schedules[] = {&Alk_Schedule , &Ca_Schedule};
char* schedule_names[] = {"Alk" , "Cal"};
#include "DOSE_menu.h"
#endif
Kod: Markera allt
#ifndef LiquidCrystal_SPI_8Bit_h
#define LiquidCrystal_SPI_8Bit_h
#include <inttypes.h>
#include "Print.h"
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
class LiquidCrystal_SPI_8Bit : public Print {
public:
LiquidCrystal_SPI_8Bit(uint8_t rs, uint8_t enable);
void init(uint8_t rs, uint8_t rw, uint8_t enable);
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
void clear();
void home();
void noDisplay();
void display();
void noBlink();
void blink();
void noCursor();
void cursor();
void scrollDisplayLeft();
void scrollDisplayRight();
void leftToRight();
void rightToLeft();
void autoscroll();
void noAutoscroll();
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
virtual void write(uint8_t);
void command(uint8_t);
private:
void send(uint8_t, uint8_t);
void write4bits(uint8_t);
void write8bits(uint8_t);
void pulseEnable();
uint8_t _rs_pin; // LOW: command. HIGH: character.
uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD.
uint8_t _enable_pin; // activated by a HIGH pulse..
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _initialized;
uint8_t _numlines,_currline;
};
#endif
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: Letar efter demo kod för 8 bit mode lcd.
Jag kanske missat något självklart, måste bara fråga varför?
Arduino Mega har väl ungefär 54 i/o pinnar
LCD biblioteket stödjer både 4 och 8 bitars styrning av LCD'n
borde finnas många pinnar kvar?
Arduino Mega har väl ungefär 54 i/o pinnar
LCD biblioteket stödjer både 4 och 8 bitars styrning av LCD'n
borde finnas många pinnar kvar?
Re: Letar efter demo kod för 8 bit mode lcd.
Jo visst är det så.
Jag försökte att göra om så man använde vanliga lcd biblioteket men fick det inte att funka, är ingen höjdare att programmera tyvärr.
Jag försökte att göra om så man använde vanliga lcd biblioteket men fick det inte att funka, är ingen höjdare att programmera tyvärr.
Re: Letar efter demo kod för 8 bit mode lcd.
har du hittat var pinnarna definieras?
skulle nog kolla lite på LiquidCrystal_SPI_8Bit.cpp istället för header filen
där står till exempel:
dom pinnarna tänkte väl inte du använda 
skulle nog kolla lite på LiquidCrystal_SPI_8Bit.cpp istället för header filen
där står till exempel:
Kod: Markera allt
void LiquidCrystal_SPI_8Bit::init(uint8_t rs, uint8_t rw, uint8_t enable)
{
pinMode(13, OUTPUT);
pinMode(12, INPUT);
pinMode(11, OUTPUT);
pinMode(10, OUTPUT);
digitalWrite(10, LOW);

Re: Letar efter demo kod för 8 bit mode lcd.
Ahh Tack!!
Nu funkar det.
Bytte till följande.
Dock hänger jag inte med vad pinMode 12 samt digitalWrite 10 gör i sammanhanget?
Skall kolla om det går att få in en DS1307 som kommer ihåg tiden. Men det är nog vatten över huvudet..
Nu funkar det.
Bytte till följande.
Kod: Markera allt
pinMode(52, OUTPUT); //13
pinMode(12, INPUT); //12
pinMode(51, OUTPUT); //11
pinMode(53, OUTPUT); //10
digitalWrite(10, LOW);
Skall kolla om det går att få in en DS1307 som kommer ihåg tiden. Men det är nog vatten över huvudet..
Re: Letar efter demo kod för 8 bit mode lcd.
pinMode(12, INPUT); // sätter pinne 12 till att vara en ingång, i ditt schema används inte pinne 12 så det borde inte spela någon roll.
digitalWrite(10, LOW); // sätter pinne 10 låg (= 0volt) den borde du nog ändra till 53 eftersom du använder den istället för 10.
kanske inte jätteviktigt utan bara för att vara säker på vilken nivå pinnen har från början.
kul att du fick igång det
ett utmärkt sätt att lära sig lite mer på är att följa kompilatorn (preprocessorn) genom koden
läsa alla "include-filer", både .h och .cpp
Det är klart du ska stoppa dit en ds1307, verkat finnas mycket kod färdigt till den klockan,
så det borde inte vara omöjligt
digitalWrite(10, LOW); // sätter pinne 10 låg (= 0volt) den borde du nog ändra till 53 eftersom du använder den istället för 10.
kanske inte jätteviktigt utan bara för att vara säker på vilken nivå pinnen har från början.
kul att du fick igång det

ett utmärkt sätt att lära sig lite mer på är att följa kompilatorn (preprocessorn) genom koden
läsa alla "include-filer", både .h och .cpp
Det är klart du ska stoppa dit en ds1307, verkat finnas mycket kod färdigt till den klockan,
så det borde inte vara omöjligt

Re: Letar efter demo kod för 8 bit mode lcd.
> pinMode(12, INPUT); // sätter pinne 12 till att vara en ingång,
> i ditt schema används inte pinne 12 så det borde inte spela någon roll.
Tvärt om, man ska absolut *inte* sätta den som ingång om den inte
används, d.v.s inte är ansluten till något. Om det inte finns pull-up
eller liknande i den aktuella hårdvaran...
> i ditt schema används inte pinne 12 så det borde inte spela någon roll.
Tvärt om, man ska absolut *inte* sätta den som ingång om den inte
används, d.v.s inte är ansluten till något. Om det inte finns pull-up
eller liknande i den aktuella hårdvaran...
Re: Letar efter demo kod för 8 bit mode lcd.
Håller med dig sodjan.
men...
I detta fall är den raden kod bara "bad programming style"
När Atmega328 startar upp är alla io pinnar ingångar utan pullup,
alla andra pinnar som inte sätts till något alls är också ingångar.
Så i det här fallet inte gör koden inte någon skillnad alls
eftersom pinnen redan innan är definierad som en ingång.

men...
I detta fall är den raden kod bara "bad programming style"
När Atmega328 startar upp är alla io pinnar ingångar utan pullup,
alla andra pinnar som inte sätts till något alls är också ingångar.
Så i det här fallet inte gör koden inte någon skillnad alls
eftersom pinnen redan innan är definierad som en ingång.

Re: Letar efter demo kod för 8-bit mode LCD
Dessutom kommer hårdvaran ändå göra den till ingång* när man aktverar SPI i master mode. Det enda viktiga är att aldrig SS blir låg ingång om man vill bibehålla master mode.
*Edit: Står det i databladet, men det verkar inte stämma för MOSI, den måste sättas till utgång om man skall få ut någon data.
*Edit: Står det i databladet, men det verkar inte stämma för MOSI, den måste sättas till utgång om man skall få ut någon data.
Senast redigerad av snigelen 8 mars 2012, 09:53:47, redigerad totalt 1 gång.
Re: Letar efter demo kod för 8-bit mode LCD
> men...
Jo, jag förstog ju det också, så det hela var lite svårkommenterat...
Att medvetet sätta pinnen som ingång är lika fel som att inte göra någonting alls...
I just detta fall, i alla fall.
Sen så kan jag tycka att det är lite av en björntjänst att börja
köra med egna nummersystem på pinnarna istället för de riktiga
PORTx/PINx. Vill man använda pinnar i grupper PORT-vis så får
man göra en extra uppslagning i någon dokumentation för att
se vilka "pins" som hör till vilken PORT. Eller missar jag något?
Visst, det sänker "ingångströskeln" så det är ju å andra sidan
inte svårt att se varför de har valt att göra så.
Jo, jag förstog ju det också, så det hela var lite svårkommenterat...

Att medvetet sätta pinnen som ingång är lika fel som att inte göra någonting alls...

I just detta fall, i alla fall.
Sen så kan jag tycka att det är lite av en björntjänst att börja
köra med egna nummersystem på pinnarna istället för de riktiga
PORTx/PINx. Vill man använda pinnar i grupper PORT-vis så får
man göra en extra uppslagning i någon dokumentation för att
se vilka "pins" som hör till vilken PORT. Eller missar jag något?
Visst, det sänker "ingångströskeln" så det är ju å andra sidan
inte svårt att se varför de har valt att göra så.
Re: Letar efter demo kod för 8-bit mode LCD
Har lyckas lagt till ytterligare en pump, det var egentligen inte så svårt, bara att kopiera ena pumpens kod och lägga till samt byta namn.
Men nu har jag problem.
Jag försöker lägga till en ds1307 RTC. Grund koden för den verkar funkar fint.
Men nu vill jag ha det så att koden nedan läser ifrån RTC'n, för som det är nu så tappar den hur mycket klockan är vid spänningsfall, vilken är himla jobbigt. Är det någon som har några tips var man skall börja?
Jag känner att jag är lite dålig på att förklara, men vi försöker.
Här är koden för 1307
Men nu har jag problem.
Jag försöker lägga till en ds1307 RTC. Grund koden för den verkar funkar fint.
Men nu vill jag ha det så att koden nedan läser ifrån RTC'n, för som det är nu så tappar den hur mycket klockan är vid spänningsfall, vilken är himla jobbigt. Är det någon som har några tips var man skall börja?
Jag känner att jag är lite dålig på att förklara, men vi försöker.
Kod: Markera allt
/****************************************************************
DOSE_clock
****************************************************************/
/***************************************************************
This file handles all of the clock setting and time conversion
functions. It handles conversion to the oddly defines tod_t
type (which is really just "#define"d to be int. I kept a seperate
name for the time type in case I want to change the way I keep
time later and also to mark those variables that need to be
scaled to 1440. By using a #define, I don't have any additional
overhead from creating a new class.
This file also contains the lengthOfTime function which returns
the length of time in the forwards direction between two times
(tod_t scaled to 1440). Regardless of which number is smaller
the second time is always assumed to be later. This is one of
the most integral parts of the computer.
************************************************************/
#ifndef DOSE_clock_h
#define DOSE_clock_h
#include "WProgram.h"
// define tod_t for a free explicit conversion to/from int
#define tod_t int
/**************** CLOCK AND TIME FUNCTION DECLARATIONS *****************/
void timePrint(time_t);
void timePrint(tod_t _tod);
void timePrint(byte _hour, byte _minute, byte _second, byte _month, byte _day, byte _year);
void time_Setup();
tod_t timeOfDay(time_t time);
tod_t inputTimeOfDay();
tod_t inputTimeOfDay(tod_t);
/* using regular int for timeOfDay so it will cast to int for calculating doses.
tod_t is defined to int. I'll have to handle the rollover at midnight manually
*/
/****************************************************************
DOSE_clock
****************************************************************/
/***************************************************************
This file handles all of the clock setting and time conversion
functions. It handles conversion to the oddly defines tod_t
type (which is really just "#define"d to be int. I kept a seperate
name for the time type in case I want to change the way I keep
time later and also to mark those variables that need to be
scaled to 1440. By using a #define, I don't have any additional
overhead from creating a new class.
This file also contains the lengthOfTime function which returns
the length of time in the forwards direction between two times
(tod_t scaled to 1440). Regardless of which number is smaller
the second time is always assumed to be later. This is one of
the most integral parts of the computer.
*****************************************************************/
/* using regular int for timeOfDay so it will cast to int for calculating doses.
tod_t is defined to int. I'll have to handle the rollover at midnight manually
*/
/********************* CLOCK FUNCTIONS ***************************/
tod_t timeOfDay(time_t _time)
{
//will return number of minutes since midnight for argument
tod_t _tod = (((tod_t)minute(_time)) + ((tod_t)hour(_time)*60)); //Real time of day
//tod_t _tod = _time % 1440; // Makes 1 second = 1 minute
return _tod;
}
void timePrint(tod_t _tod)
{
if ((_tod / 60)<10) LCD.print("0");
LCD.print(_tod / 60);
LCD.print(":");
if (((_tod) % 60)<10) LCD.print("0");
LCD.print((_tod) % 60);
}
void timePrint(time_t time)
{
LCD.clear();
if (hour(time)<10) LCD.print("0");
LCD.print(hour(time));
LCD.print(":");
if (minute(time)<10) LCD.print("0");
LCD.print(minute(time));
LCD.print(":");
if (second(time)<10) LCD.print("0");
LCD.print(second(time));
LCD.setCursor(0,1);
LCD.print(weekday(time));
LCD.print(" ");
if (month(time)<10) LCD.print("0");
LCD.print(month(time));
LCD.print("-");
if (day(time)<10) LCD.print("0");
LCD.print(day(time));
// LCD.print("-");
//LCD.print(year(time));
}
void timePrint(byte _hour, byte _minute, byte _second, byte _day, byte _month, byte _year)
{
LCD.clear();
if (_hour<10) LCD.print("0");
LCD.print(int (_hour));
LCD.print(":");
if (_minute<10) LCD.print("0");
LCD.print(int (_minute));
LCD.print(":");
if (_second<10) LCD.print("0");
LCD.print(int (_second));
LCD.setCursor(0,1);
if (_month<10) LCD.print("0");
LCD.print(int (_month));
LCD.print("-");
if (_day<10) LCD.print("0");
LCD.print(int (_day));
LCD.print("-");
LCD.print(int (_year));
}
void timeSetup()
{
// This is the function used to set the date and time
int set_hour = hour(current_time);
int set_minute = minute(current_time);
int set_second = 0;
int set_month = month(current_time);
int set_day = day(current_time);
int set_year = year(current_time);
LCD.cursor();
timePrint(set_hour, set_minute, set_second, set_month, set_day, set_year);
inputTheNumber(set_month, 2, 1, 12, 0, 1);
inputTheNumber(set_day, 2, 1, 31, 3, 1);
// inputTheNumber(set_year, 2, 10, 99, 6, 1);
inputTheNumber(set_hour, 2, 0, 23, 0, 0);
inputTheNumber(set_minute, 2, 0, 59, 3, 0);
inputTheNumber(set_second, 2, 0, 59, 6, 0);
//unsigned long timeSpoof = ((set_hour * 60) + (set_minute));
//setTime(timeSpoof);
setTime(set_hour, set_minute, set_second, set_day, set_month, set_year);
LCD.noCursor();
}
// Use a tod_t as an argument to set a default time
tod_t inputTimeOfDay(tod_t _time)
{
// Used to input a time of day in hour : minute format
tod_t set_tod;
int set_hour = (_time / 60);
int set_minute = (_time % 60);
LCD.setCursor(0,1);
set_tod =(((tod_t)set_minute) + ((tod_t)set_hour * 60));
timePrint(set_tod);
inputTheNumber(set_hour, 2, 0, 23, 0, 1);
LCD.setCursor(0,1);
set_tod = (((tod_t)set_minute) + ((tod_t)set_hour * 60));
timePrint(set_tod);
inputTheNumber(set_minute, 2, 0, 59, 3, 1);
LCD.setCursor(0,1);
set_tod = (((tod_t)set_minute) + ((tod_t)set_hour * 60));
timePrint(set_tod);
while(button1==LOW); // wait for button release leaving inputTheNumber
while(button1==HIGH); // require second button push to confirm time before exit
while(button1==LOW); // wait for release
return set_tod;
}
tod_t lengthOfTime(tod_t _start, tod_t _end)
{
// Calculates the length of time between two numbers in tod_t format (minutes since midnight)
if (_start < _end)
{
return (_end - _start); // Simple case
}
else if (_start > _end)
{
return ((MIDNIGHT - _start) + _end); // Handle the rollover
}
else
{
return (MIDNIGHT); // If start = end, return length of day
}
}
#endif
Här är koden för 1307
Kod: Markera allt
#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68
#include "LiquidCrystal_SPI_8Bit.h"
int backLight = 13; // pin 13 will control the backlight
LiquidCrystal_SPI_8Bit LCD(8,53);
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour));
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.receive() & 0x7f);
*minute = bcdToDec(Wire.receive());
*hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.receive());
*dayOfMonth = bcdToDec(Wire.receive());
*month = bcdToDec(Wire.receive());
*year = bcdToDec(Wire.receive());
}
void setup()
{
pinMode(backLight, OUTPUT);
digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
Serial.begin(9600);
// Change these values to what you want to set your clock to.
// You probably only want to set your clock once and then remove
// the setDateDs1307 call.
second = 32;
minute = 27;
hour = 00;
dayOfWeek = 5;
dayOfMonth = 8;
month = 03;
year = 12;
//setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
LCD.begin(20, 2); // tells Arduino the LCD dimensions
}
void loop()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
LCD.clear(); // clear LCD screen
LCD.setCursor(0,0);
LCD.print(" ");
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);
LCD.setCursor(0,1);
LCD.print(" ");
switch(dayOfWeek){
case 1:
LCD.print("Sun");
break;
case 2:
LCD.print("Mon");
break;
case 3:
LCD.print("Tue");
break;
case 4:
LCD.print("Wed");
break;
case 5:
LCD.print("Thu");
break;
case 6:
LCD.print("Fri");
break;
case 7:
LCD.print("Sat");
break;
}
LCD.print(" ");
LCD.print(month, DEC);
LCD.print("/");
LCD.print(dayOfMonth, DEC);
LCD.print("/20");
LCD.print(year, DEC);
delay(1000);
}
Re: Letar efter demo kod för 8-bit mode LCD
Alltså att *Arduinon* tappar hur mycket klockan är vid spänningsfall?
I så fall är det ju förväntat. Men om du menar ds1307 så vet i tusan...
> Är det någon som har några tips var man skall börja?
Lite oklart vad som är problemet, men du ska väl anropa getDateDs1307() !?
I så fall är det ju förväntat. Men om du menar ds1307 så vet i tusan...

> Är det någon som har några tips var man skall börja?
Lite oklart vad som är problemet, men du ska väl anropa getDateDs1307() !?