Letar efter demo kod för 8-bit mode LCD

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Jonaz
Inlägg: 2358
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Letar efter demo kod för 8-bit mode LCD

Inlägg av Jonaz »

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?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46987
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av TomasL »

Du kan ju börja med ett schema och lite relevant kod, så kanske....
Användarvisningsbild
Jonaz
Inlägg: 2358
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av Jonaz »

Jag tänkte lite generellt bara.
Men visst kan jag lägga upp det, strax.
Användarvisningsbild
Jonaz
Inlägg: 2358
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av Jonaz »

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.
DOSING_COMPUTER_LIBRARIES.zip
DOSING_COMPUTER_6.zip
bb_img_w_bjt.jpg

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
LiquidCrystal_SPI_8Bit biblioteket i sin helhet.

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.
nifelheim
Den första
Inlägg: 2490
Blev medlem: 27 mars 2008, 22:31:16
Ort: stockholm

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av nifelheim »

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?
Användarvisningsbild
Jonaz
Inlägg: 2358
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av Jonaz »

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.
nifelheim
Den första
Inlägg: 2490
Blev medlem: 27 mars 2008, 22:31:16
Ort: stockholm

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av nifelheim »

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:

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);
  
dom pinnarna tänkte väl inte du använda :wink:
Användarvisningsbild
Jonaz
Inlägg: 2358
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av Jonaz »

Ahh Tack!!
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);
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..
nifelheim
Den första
Inlägg: 2490
Blev medlem: 27 mars 2008, 22:31:16
Ort: stockholm

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av nifelheim »

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 :wink:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av sodjan »

> 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...
nifelheim
Den första
Inlägg: 2490
Blev medlem: 27 mars 2008, 22:31:16
Ort: stockholm

Re: Letar efter demo kod för 8 bit mode lcd.

Inlägg av nifelheim »

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. :wink:
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: Letar efter demo kod för 8-bit mode LCD

Inlägg av snigelen »

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.
Senast redigerad av snigelen 8 mars 2012, 09:53:47, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Letar efter demo kod för 8-bit mode LCD

Inlägg av sodjan »

> 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å.
Användarvisningsbild
Jonaz
Inlägg: 2358
Blev medlem: 4 november 2003, 22:06:33
Ort: Huddinge

Re: Letar efter demo kod för 8-bit mode LCD

Inlägg av Jonaz »

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.

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);
} 
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Letar efter demo kod för 8-bit mode LCD

Inlägg av sodjan »

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() !?
Skriv svar