Avr Multitasking problems??

Go To Last Post
46 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have created what according to me is correct but doesn't behave like it should. I have tried to find the problem but was unable to detect it can you please help me here.

//
//    Co-operative multitasking framework tutorial code
//    (c)Russell Bull 2010. Free for any use.
//    Code built for a Mega168 @ 16MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "I2C_Master_H_file.h" //for rtc
#include "lcd.h"  //for the lcd 
#include "debounce.h" //for button debounce

void init_devices(void);
void timer_0_init(void);
void reset_task(char tsk);
void set_task(char tsk);
void task_dispatch(void);
void task0(void);
void task1(void);
void task2(void);
void task3(void);
void task4(void);
void task5(void);
void task6(void);
void task7(void);
//--------------------------------------------------------------------------------------------------------------
#define DS1307_WRITE_ADDR    0xD0    /* Define RTC DS1307 slave write address */
#define DS1307_READ_ADDR    0xD1    /* Make LSB bit high of slave address for read */
int second,minute,hour,day,date,month,year;
//--------------------------------------------------------------------------------------------------------------
#define DEGREE_SYMBOL 0xdf
//--------------------------------------------------------------------------------------------------------------
#define NUM_TASKS 8
char task_bits = 0;  /* lsb is hi priority task */
volatile char tick_flag = 0;    /* if non-zero, a tick has elapsed */
unsigned int task_timers[NUM_TASKS]={0,0,0,0,0,0,0,0};                  /* init the timers to 0 on startup */
static const PROGMEM char bit_mask[]={1,2,4,8,16,32,64,128};            /* value -> bit mask xlate table */
//---------------------------------------------------------------------------------------------------------------
void RTC_Read_Clock(char read_clock_address)
{
    I2C_Start(DS1307_WRITE_ADDR);/* Start I2C communication with RTC */
    I2C_Write(read_clock_address);    /* Write address to read */
    I2C_Repeated_Start(DS1307_READ_ADDR);/* Repeated start with device read address */

    second = I2C_Read_Ack();    /* Read second */
    minute = I2C_Read_Ack();    /* Read minute */
    hour = I2C_Read_Nack();        /* Read hour with Nack */
    I2C_Stop();            /* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
    I2C_Start(DS1307_WRITE_ADDR);
    I2C_Write(read_calendar_address);
    I2C_Repeated_Start(DS1307_READ_ADDR);

    day = I2C_Read_Ack();        /* Read day */
    date = I2C_Read_Ack();        /* Read date */
    month = I2C_Read_Ack();        /* Read month */
    year = I2C_Read_Nack();        /* Read the year with Nack */
    I2C_Stop();            /* Stop i2C communication */
}

void ADC_Init(){
    DDRA = 0x00;            /* Make ADC port as input */
    ADCSRA = 0x87;          /* Enable ADC, with freq/128  */
    ADMUX = 0x40;           /* Vref: Avcc, ADC channel: 0 */
}

int ADC_Read(char channel)
{
    ADMUX = 0x40 | (channel & 0x07);   /* set input channel to read */
    ADCSRA |= (1<<ADSC);               /* Start ADC conversion */
    while ((ADCSRA & (1<<ADSC)));     /* Wait until end of conversion by polling ADC interrupt flag */
    return ADCW;                       /* Return ADC word */
}

int main(void) 
{ 

  init_devices();
//start at least one task here

    set_task(5);

//set_task(7);    //task7 runs
//set_task(6);    //task6 runs

//      main loop 

  while(1)
    {
    if (tick_flag)
      {
      tick_flag = 0;
      task_dispatch();              // well.... 
      }
    }
  return 0;
} 
//
//    a task gets dispatched on every tick_flag tick (10ms)
//
void task_dispatch(void)
{
  /* scan the task bits for an active task and execute it */

  char task;
    

/* take care of the task timers. if the value ==0 skip it
    else decrement it. If it decrements to zero, activate the task associated with it */

  task=0;
  while (task < NUM_TASKS )
    {
    if (task_timers[task])
       {
         task_timers[task]--;            /* dec the timer */
       if (task_timers[task] == 0 )
               {
            set_task(task); /* if ==0 activate the task bit */
            }
       }
    task++;
    }

  task = 0; /* start at the most significant task */
  while (task <= NUM_TASKS )
    {
      if ((task_bits & pgm_read_byte(&bit_mask[task])))
              {
              break; /* if activate task found..*/
            }
      task++;         /* else try the next one */
    }
  switch(task)            /* if task bit is active..execute the task */
    {
    case 0:
      task0();
      break;
    case 1:
      task1();
      break;
    case 2:
      task2();
      break;
    case 3:
      task3();
      break;
    case 4:
      task4();
      break;
    case 5:
      task5();
      break;
    case 6:
      task6();
      break;
    case 7:
      task7();
      break;
    default:
      break;                  /* no task was active!! */
    }                       
}

// enable a task for execution
void set_task(char tsk)
{
  task_bits |= pgm_read_byte(&bit_mask[tsk]);       /* sets a task bit */
}
// disable a task from executing
void reset_task(char tsk)
{
  task_bits &= (~pgm_read_byte(&bit_mask[tsk]));  /* resets a task bit */
}

void task0(void)
{
    
  reset_task(0);
}
void task1(void)
{
    if (button_down(BUTTON1_MASK))
    {
      
        PORD ^= 1<<PD4;
    }
  reset_task(1);
}
void task2(void)
{
    if (button_down(BUTTON2_MASK))
    {
      
        PORTD ^= 1<<PD7;
    }
  reset_task(2);
}
void task3(void)
{
      char Temperature[10];
      float celsius;
      mylcd_string(1, 0,"TEMPERATURE");
      celsius = (float)ADC_Read(0)*4.88 / 10.0;
      sprintf(Temperature,"%d%cC  ", (int)celsius, DEGREE_SYMBOL);
      mylcd_string(1,12,Temperature);
      reset_task(3);
}
void task4(void)
{
    
    reset_task(4);
}
void task5(void)
{
//    Rtc time and date are displayed here

    char buffer[40];
    RTC_Read_Clock(0);    /* Read clock with second add. i.e location is 0 */
    sprintf(buffer, "%02x:%02x:%02x ", (hour), minute, second);
    mylcd_string(0,0,buffer);
    RTC_Read_Calendar(3);    /* Read calendar with day address i.e location is 3 */
    sprintf(buffer, "%02x/%02x/%02x  ", date,month, year);
    mylcd_string(0, 1, buffer);
    reset_task(5);
    task_timers[5] = 50;    //run twice per second
}

void task6(void)
{

reset_task(6);
}

void task7(void)
{

reset_task(7);
}

//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 cli(); //disable all interrupts
    DDRA = 0x00;//for temperature sensor
    DDRB = 0xff;//outputs for lcd
    PORTB = 0x00;
    PORTC = 0x00; // for rtc chip ds1307
    DDRC  = 0x00;
    PORTD = 0x0f;    //pull-up enables for 3 pushbuttons
    DDRD  = 0xf0;    //2 o/p for relays, 1 o/p for LED, 1 o/p for TXD and 3 i/p for pushbuttons

 timer_0_init();
 debounce_init();
 
 sei(); //re-enable interrupts
 //all peripherals are now initialized
}
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer_0_init(void)
{
 TCCR0 = 0x00; //stop
 TCNT0 = 0x00; //set count
 TCCR0 = 0x02;    //CTC mode
 OCR0 = 0x9C;
 TCCR0 = 0x05; //start timer
}

ISR(TIMER0_COMP_vect)       //make sure this is correct - the compiler will complain if it's not
{
 //TIMER0 has overflowed
     tick_flag = 1;
     debounce();
}

I am using peter's fluery lcd library and danni's library for button debounce both of which great worked on my other projects and ofcourse Kartman's multitasking tutorial as the base of my project.

This topic has a solution.

anshumaan kumar

Last Edited: Tue. Dec 24, 2019 - 09:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You’ve not said what the problem actually is!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have tested this code on Atmel studio 7 and it shows no errors and also I have simulated it on proteus on which it shows nothing but a blank lit display.Proteus simulation Test

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
You’ve not said what the problem actually is!

Sorry I had forgotten that and I was in the process of posting the problem when you arrived

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where do you initialise the lcd?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is continuing from your previous thread:

 

https://www.avrfreaks.net/forum/...

 

Don't just jump off onto a new thread - that causes confusion!

 

Make a post in the original thread to say where the discussion has gone!

 

Anshumaan wrote:
I have tested this code on Atmel studio 7 and it shows no errors

As noted in your previous thread, that is not testing the code;  that simply shows that you have no syntax errors - it is no guarantee that it will function correctly!

 

https://www.avrfreaks.net/commen...

 

 I have simulated it on proteus 

 

So, again, as stated in your previous thread, use you simulator to find out where it's going wrong!

 

https://www.avrfreaks.net/commen...

 

Proteus is a 3rd-party tool from an independent supplier - it has nothing to do with Microchip 

 

So, for help in learning to use Proteus, you need to go to Labcenter:

 

https://www.avrfreaks.net/commen...

 

https://www.avrfreaks.net/commen...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Dec 5, 2019 - 11:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Where do you initialise the lcd?

Not only that, but there are no pull up resistors (4k7) on the I2C SDA/SCL lines, so once the OP has the LCD working the RTC will not work as well.

 

Time to take a moment to verify your over all design and see to the details of the project.

It looks like your rushing in to coding before verifying you have completed the written design and checked all the system requirements and h/w details.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

Last Edited: Thu. Dec 5, 2019 - 02:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:
It looks like your rushing in to coding before verifying you have completed the written design and checked all the system requirements and h/w details

 

See: https://www.avrfreaks.net/commen...

 

and: https://www.avrfreaks.net/commen...

 

And another frequent beginner's mistake is to try to do everything all at once, then throw it all straight onto the Target. And wonder why it "doesn't work".

 

https://www.avrfreaks.net/commen...

 

 

EDIT

 

Just to note that these apply to both hardware development and software development

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Dec 5, 2019 - 02:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Let me speak now ,

 

1. 

Kartman wrote:
Where do you initialise the lcd?

I was not expecting that but yes that is a mistake that I had made and as I wasn't expecting to make such an error I overlooked it.

Now solved.

 

2.

awneil wrote:
Don't just jump off onto a new thread - that causes confusion!

Sorry ,but I felt that as that discussion question's was answered hence I moved here as The 'topic' is same but there is a new problem so I thought it would be a good idea to create a new thread.

Sorry next time I will try to be at the same place for a single topic.

 

3.

ki0bk wrote:
Not only that, but there are no pull up resistors (4k7) on the I2C SDA/SCL lines, so once the OP has the LCD working the RTC will not work as well.

Sorry to question you but I think you had never used 'proteus' you can use the ds1307 here without the resistors and the crystal just like this DS1307 without crystal and resistor

Here we can see that it works, also for the hardware I have a module which have all the necessary things built in so I don't need to worry. Please don't be angry I am just clearing things ,so no offense.

Nevertheless I have changed what you have indicated.

 

4.

awneil wrote:
And another frequent beginner's mistake is to try to do everything all at once, then throw it all straight onto the Target. And wonder why it "doesn't work".

I see you are actually correct but most of the things (coding) that I am using here I know, the only thing that is new to me is the multitasking which is why we all are here you as my instructors / teachers , etc and I am as your student. 

No matter what happens please guide me at every point , I want to be as expert as you people are and hence will follow each and every advice even it takes me hundreds of rebuilds of my codesmiley.

Now back where I have left :-

 

Things that I have fixed:-

1.I have initialized the lcd properly.

2.I have connected the ds1307 in the official and correct manner.

 

Problems that I am encountering still:-

1. Lcd is still blank. 

2. I am getting actually nothing as the output.

 

//
//    Co-operative multitasking framework tutorial code
//    (c)Russell Bull 2010. Free for any use.
//    Code built for a Mega168 @ 16MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "I2C_Master_H_file.h" //for rtc
#include "lcd.h"  //for the lcd
#include "debounce.h" //for button debounce

void init_devices(void);
void timer_0_init(void);
void reset_task(char tsk);
void set_task(char tsk);
void task_dispatch(void);
void task0(void);
void task1(void);
void task2(void);
void task3(void);
void task4(void);
void task5(void);
void task6(void);
void task7(void);
//--------------------------------------------------------------------------------------------------------------
#define DS1307_WRITE_ADDR    0xD0    /* Define RTC DS1307 slave write address */
#define DS1307_READ_ADDR    0xD1    /* Make LSB bit high of slave address for read */
int second,minute,hour,day,date,month,year;
//--------------------------------------------------------------------------------------------------------------
#define DEGREE_SYMBOL 0xdf
//--------------------------------------------------------------------------------------------------------------
#define NUM_TASKS 8
char task_bits = 0;  /* lsb is hi priority task */
volatile char tick_flag = 0;    /* if non-zero, a tick has elapsed */
unsigned int task_timers[NUM_TASKS]={0,0,0,0,0,0,0,0};                  /* init the timers to 0 on startup */
static const PROGMEM char bit_mask[]={1,2,4,8,16,32,64,128};            /* value -> bit mask xlate table */
//---------------------------------------------------------------------------------------------------------------
void RTC_Read_Clock(char read_clock_address)
{
    I2C_Start(DS1307_WRITE_ADDR);/* Start I2C communication with RTC */
    I2C_Write(read_clock_address);    /* Write address to read */
    I2C_Repeated_Start(DS1307_READ_ADDR);/* Repeated start with device read address */

    second = I2C_Read_Ack();    /* Read second */
    minute = I2C_Read_Ack();    /* Read minute */
    hour = I2C_Read_Nack();        /* Read hour with Nack */
    I2C_Stop();            /* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
    I2C_Start(DS1307_WRITE_ADDR);
    I2C_Write(read_calendar_address);
    I2C_Repeated_Start(DS1307_READ_ADDR);

    day = I2C_Read_Ack();        /* Read day */
    date = I2C_Read_Ack();        /* Read date */
    month = I2C_Read_Ack();        /* Read month */
    year = I2C_Read_Nack();        /* Read the year with Nack */
    I2C_Stop();            /* Stop i2C communication */
}

void ADC_Init(){
    DDRA = 0x00;            /* Make ADC port as input */
    ADCSRA = 0x87;          /* Enable ADC, with freq/128  */
    ADMUX = 0x40;           /* Vref: Avcc, ADC channel: 0 */
}

int ADC_Read(char channel)
{
    ADMUX = 0x40 | (channel & 0x07);   /* set input channel to read */
    ADCSRA |= (1<<ADSC);               /* Start ADC conversion */
    while ((ADCSRA & (1<<ADSC)));     /* Wait until end of conversion by polling ADC interrupt flag */
    return ADCW;                       /* Return ADC word */
}

int main(void)
{ 

  init_devices();
//start at least one task here

    set_task(5);

//set_task(7);    //task7 runs
//set_task(6);    //task6 runs

//      main loop 

  while(1)
    {
    if (tick_flag)
      {
      tick_flag = 0;
      task_dispatch();              // well....
      }
    }
  return 0;
}
//
//    a task gets dispatched on every tick_flag tick (10ms)
//
void task_dispatch(void)
{
  /* scan the task bits for an active task and execute it */

  char task;

/* take care of the task timers. if the value ==0 skip it
    else decrement it. If it decrements to zero, activate the task associated with it */

  task=0;
  while (task < NUM_TASKS )
    {
    if (task_timers[task])
       {
         task_timers[task]--;            /* dec the timer */
       if (task_timers[task] == 0 )
               {
            set_task(task); /* if ==0 activate the task bit */
            }
       }
    task++;
    }

  task = 0; /* start at the most significant task */
  while (task <= NUM_TASKS )
    {
      if ((task_bits & pgm_read_byte(&bit_mask[task])))
              {
              break; /* if activate task found..*/
            }
      task++;         /* else try the next one */
    }
  switch(task)            /* if task bit is active..execute the task */
    {
    case 0:
      task0();
      break;
    case 1:
      task1();
      break;
    case 2:
      task2();
      break;
    case 3:
      task3();
      break;
    case 4:
      task4();
      break;
    case 5:
      task5();
      break;
    case 6:
      task6();
      break;
    case 7:
      task7();
      break;
    default:
      break;                  /* no task was active!! */
    }
}

// enable a task for execution
void set_task(char tsk)
{
  task_bits |= pgm_read_byte(&bit_mask[tsk]);       /* sets a task bit */
}
// disable a task from executing
void reset_task(char tsk)
{
  task_bits &= (~pgm_read_byte(&bit_mask[tsk]));  /* resets a task bit */
}

void task0(void)
{

  reset_task(0);
}
void task1(void)
{
    if (button_down(BUTTON1_MASK))
    {

        PORTD ^= 1<<PD4;
    }
  reset_task(1);
}
void task2(void)
{
    if (button_down(BUTTON2_MASK))
    {

        PORTD ^= 1<<PD7;
    }
  reset_task(2);
}
void task3(void)
{
      char Temperature[10];
      float celsius;
      mylcd_string(1, 0,"TEMPERATURE");
      celsius = (float)ADC_Read(0)*4.88 / 10.0;
      sprintf(Temperature,"%d%cC  ", (int)celsius, DEGREE_SYMBOL);
      mylcd_string(1,12,Temperature);
      reset_task(3);
}
void task4(void)
{

    reset_task(4);
}
void task5(void)
{
//    Rtc time and date are displayed here

    char buffer[40];
    RTC_Read_Clock(0);    /* Read clock with second add. i.e location is 0 */
    sprintf(buffer, "%02x:%02x:%02x ", (hour), minute, second);
    mylcd_string(0,0,buffer);
    RTC_Read_Calendar(3);    /* Read calendar with day address i.e location is 3 */
    sprintf(buffer, "%02x/%02x/%02x  ", date,month, year);
    mylcd_string(0, 1, buffer);
    reset_task(5);
    task_timers[5] = 50;    //run twice per second
}

void task6(void)
{

reset_task(6);
}

void task7(void)
{

reset_task(7);
}

//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 cli(); //disable all interrupts
    DDRA = 0x00;//for temperature sensor
    DDRB = 0xff;//outputs for lcd
    PORTB = 0x00;
    PORTC = 0x00; // for rtc chip ds1307
    DDRC  = 0x00;
    PORTD = 0x0f;    //pull-up enables for 3 pushbuttons
    DDRD  = 0xf0;    //2 o/p for relays, 1 o/p for LED, 1 o/p for TXD and 3 i/p for pushbuttons
 lcd_init(LCD_DISP_ON);
 timer_0_init();
 debounce_init();

 sei(); //re-enable interrupts
 //all peripherals are now initialized
}
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer_0_init(void)
{
 TCCR0 = 0x00; //stop
 TCNT0 = 0x00; //set count
 TCCR0 = 0x02;    //CTC mode
 OCR0 = 0x9C;
 TCCR0 = 0x05; //start timer
}

ISR(TIMER0_COMP_vect)       //make sure this is correct - the compiler will complain if it's not
{
 //TIMER0 has overflowed
     tick_flag = 1;
     debounce();
}

The modified circuit is here:-

Modified Circuit

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

as I wasn't expecting to make such an error

Well, that is good to know cheeky 

 

What specific debugging have you done?  What have you found?  Did you verify you are actually executing the LCD init code & the code that puts something to the display?

Also note, simulation of timer cycles can be problematic...what take only 5 millseconds in a real chip could take much much longer, depending on the simulation method (I am not familiar with Proteus).  So you might say "why is my led not flashing" & it is simply taking 2 minutes to flash, instead of 2 seconds.  So you don't see it & claim it never happens--- you need to monitor what is actually being executed very carefully, so as not to jump to a false conclusion.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
What specific debugging have you done?

I have tried to start up the simulation process at different speeds but unfortunately have received the same result apart from this I have tried nothing just looking at the code for some unimaginable error I might have typed in.

avrcandies wrote:
so as not to jump to a false conclusion.

Yes,  you are right that is why I am checking the simulation in every way possible by the way thanks really appreciate your efforts.

Also I am getting ready with the breadboard I will test this code on the hardware too.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If Proteus lets you simulate DS1307 on I2C without pull-up resistors then it is rather failing in its design to be a true simulation of real world electronics.
.
Simulators are fun toys and can sometimes help a bit in the design of something but I would not trust their behaviour as "gospel".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:

Here we can see that it works, also for the hardware I have a module which have all the necessary things built in so I don't need to worry. Please don't be angry I am just clearing things ,so no offense.

Nevertheless I have changed what you have indicated.

No offense taken, glad it works now (LCD, or does it, next comment says it does not, oh well)

Your simulator may work ok with out the pull ups, and current limiting resistors for the LEDs as well, but the real h/w will have problems with it, besides, we can not see your real h/w so have no knowledge that they exist, as we can only go on what you have shown us.  So forgive us if we insist on things that are not shown but exist. 

So not shown:

1) series resistors for LED's (if vcc is 5v, 330 ohm will work well)

2) bypass caps on VCC/GND pin pair, and AVCC/GND pin pair

3) AREF should NOT be tied to VCC, as damage will occur if ADC ref is set to use an internal source, AREF pin should have a 100nf cap to gnd only.

4) although not required if using internal port pin pullups, pull up resistors on your buttons can't hurt.

5) your LM35 temp sensor should have a bypass cap(100nf works well here too) on its VCC/GND pin as well.

6) some here would also recommend a 10k pull up on the reset pin, I've never used one, but YMMV

These may already exist, you just have not shown them, so we don't know if they do or not.

Good luck with your project.

Jim

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You still haven't shown us any code that initialises the LCD.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


 

You still haven't shown us any code that initialises the LCD.

Oh, no worries..believe & it will work

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This doesn't look right:

TCCR0 = 0x00; //stop
 TCNT0 = 0x00; //set count
 TCCR0 = 0x02;    //CTC mode
 OCR0 = 0x9C;
 TCCR0 = 0x05; //start timer

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for replying soo late I was kinda busy in some other work and I hate to leave my tinkering work with the avr. I am actually typing more sorry(s) than replying to you guys. Well you know the main problem for me is that I know how to drive these things(timer, lcd, rtc , etc)individually but I fails to combine them this is the problem I encounter the most.

Well let's come to the point :- 

1.

clawson wrote:
I would not trust their behaviour as "gospel".

Neither I do ,I just use this as a testing ground for my code so that I can program the avr with the best code that could complete the requirement.

 

2.

ki0bk wrote:

Anshumaan wrote:

Here we can see that it works, also for the hardware I have a module which have all the necessary things built in so I don't need to worry. Please don't be angry I am just clearing things ,so no offense.

Nevertheless I have changed what you have indicated.

No offense taken, glad it works now (LCD, or does it, next comment says it does not, oh well)

Your simulator may work ok with out the pull ups, and current limiting resistors for the LEDs as well, but the real h/w will have problems with it, besides, we can not see your real h/w so have no knowledge that they exist, as we can only go on what you have shown us.  So forgive us if we insist on things that are not shown but exist.

(a).Thanks I thought I would piss someone off by questioning them , well the lcd works means that it's lighted up but doesn't give anything(it gives only a blank screen).

(b).Sorry I will post the hardware once I will mend the code to a running state.  

(c). The hardware that I use mostly consists of "modules" which are like just connect and play with them although I know how to connect these things(like the bare ds1307) I still prefer modules for my tinkering as they prevent the possibility of loose wires and other wiring problems.

(d.)A big thanks to you for providing a ton of hardware knowledge to me.yes

 

3.

Brian Fairchild wrote:
You still haven't shown us any code that initialises the LCD.

Well as I have stated above(#1) I am using peter fluery's library as my lcd basis you can check out the initialization code in the library I have actually initialized the lcd correctly according to the library.

Below is the library :-

http://www.peterfleury.epizy.com...

 

4.

avrcandies wrote:
Oh, no worries..believe & it will work

cheekyFunny post. Well nothing works without putting the work in it, I think my efforts are still not enough.

 

5.

jaksel wrote:

This doesn't look right:

TCCR0 = 0x00; //stop
 TCNT0 = 0x00; //set count
 TCCR0 = 0x02;    //CTC mode
 OCR0 = 0x9C;
 TCCR0 = 0x05; //start timer

No sir, this is totally right I have made this more readable in my code here you can see this. Thanks for replying.

//
//    Co-operative multitasking framework tutorial code
//    (c)Russell Bull 2010. Free for any use.
//    Code built for a Mega168 @ 16MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "I2C_Master_H_file.h" //for rtc
#include "lcd.h"  //for the lcd
#include "debounce.h" //for button debounce

void init_devices(void);
void timer_0_init(void);
void reset_task(char tsk);
void set_task(char tsk);
void task_dispatch(void);
void task0(void);
void task1(void);
void task2(void);
void task3(void);
void task4(void);
void task5(void);
void task6(void);
void task7(void);
//--------------------------------------------------------------------------------------------------------------
#define DS1307_WRITE_ADDR    0xD0    /* Define RTC DS1307 slave write address */
#define DS1307_READ_ADDR    0xD1    /* Make LSB bit high of slave address for read */
int second,minute,hour,day,date,month,year;
//--------------------------------------------------------------------------------------------------------------
#define DEGREE_SYMBOL 0xdf
//--------------------------------------------------------------------------------------------------------------
#define NUM_TASKS 8
char task_bits = 0;  /* lsb is hi priority task */
volatile char tick_flag = 0;    /* if non-zero, a tick has elapsed */
unsigned int task_timers[NUM_TASKS]={0,0,0,0,0,0,0,0};                  /* init the timers to 0 on startup */
static const PROGMEM char bit_mask[]={1,2,4,8,16,32,64,128};            /* value -> bit mask xlate table */
//---------------------------------------------------------------------------------------------------------------
void RTC_Read_Clock(char read_clock_address)
{
    I2C_Start(DS1307_WRITE_ADDR);/* Start I2C communication with RTC */
    I2C_Write(read_clock_address);    /* Write address to read */
    I2C_Repeated_Start(DS1307_READ_ADDR);/* Repeated start with device read address */

    second = I2C_Read_Ack();    /* Read second */
    minute = I2C_Read_Ack();    /* Read minute */
    hour = I2C_Read_Nack();        /* Read hour with Nack */
    I2C_Stop();            /* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
    I2C_Start(DS1307_WRITE_ADDR);
    I2C_Write(read_calendar_address);
    I2C_Repeated_Start(DS1307_READ_ADDR);

    day = I2C_Read_Ack();        /* Read day */
    date = I2C_Read_Ack();        /* Read date */
    month = I2C_Read_Ack();        /* Read month */
    year = I2C_Read_Nack();        /* Read the year with Nack */
    I2C_Stop();            /* Stop i2C communication */
}

void ADC_Init(){
    DDRA = 0x00;            /* Make ADC port as input */
    ADCSRA = 0x87;          /* Enable ADC, with freq/128  */
    ADMUX = 0x40;           /* Vref: Avcc, ADC channel: 0 */
}

int ADC_Read(char channel)
{
    ADMUX = 0x40 | (channel & 0x07);   /* set input channel to read */
    ADCSRA |= (1<<ADSC);               /* Start ADC conversion */
    while ((ADCSRA & (1<<ADSC)));     /* Wait until end of conversion by polling ADC interrupt flag */
    return ADCW;                       /* Return ADC word */
}

int main(void)
{ 

  init_devices();
//start at least one task here

    set_task(5);

//set_task(7);    //task7 runs
//set_task(6);    //task6 runs

//      main loop 

  while(1)
    {
    if (tick_flag)
      {
      tick_flag = 0;
      task_dispatch();              // well....
      }
    }
  return 0;
}
//
//    a task gets dispatched on every tick_flag tick (10ms)
//
void task_dispatch(void)
{
  /* scan the task bits for an active task and execute it */

  char task;

/* take care of the task timers. if the value ==0 skip it
    else decrement it. If it decrements to zero, activate the task associated with it */

  task=0;
  while (task < NUM_TASKS )
    {
    if (task_timers[task])
       {
         task_timers[task]--;            /* dec the timer */
       if (task_timers[task] == 0 )
               {
            set_task(task); /* if ==0 activate the task bit */
            }
       }
    task++;
    }

  task = 0; /* start at the most significant task */
  while (task <= NUM_TASKS )
    {
      if ((task_bits & pgm_read_byte(&bit_mask[task])))
              {
              break; /* if activate task found..*/
            }
      task++;         /* else try the next one */
    }
  switch(task)            /* if task bit is active..execute the task */
    {
    case 0:
      task0();
      break;
    case 1:
      task1();
      break;
    case 2:
      task2();
      break;
    case 3:
      task3();
      break;
    case 4:
      task4();
      break;
    case 5:
      task5();
      break;
    case 6:
      task6();
      break;
    case 7:
      task7();
      break;
    default:
      break;                  /* no task was active!! */
    }
}

// enable a task for execution
void set_task(char tsk)
{
  task_bits |= pgm_read_byte(&bit_mask[tsk]);       /* sets a task bit */
}
// disable a task from executing
void reset_task(char tsk)
{
  task_bits &= (~pgm_read_byte(&bit_mask[tsk]));  /* resets a task bit */
}

void task0(void)
{

  reset_task(0);
}
void task1(void)
{
    if (button_down(BUTTON1_MASK))
    {

        PORTD ^= 1<<PD4;
    }
  reset_task(1);
}
void task2(void)
{
    if (button_down(BUTTON2_MASK))
    {

        PORTD ^= 1<<PD7;
    }
  reset_task(2);
}
void task3(void)
{
      char Temperature[10];
      float celsius;
      mylcd_string(1, 0,"TEMPERATURE");
      celsius = (float)ADC_Read(0)*4.88 / 10.0;
      sprintf(Temperature,"%d%cC  ", (int)celsius, DEGREE_SYMBOL);
      mylcd_string(1,12,Temperature);
      reset_task(3);
}
void task4(void)
{

    reset_task(4);
}
void task5(void)
{
//    Rtc time and date are displayed here

    char buffer[40];
    RTC_Read_Clock(0);    /* Read clock with second add. i.e location is 0 */
    sprintf(buffer, "%02x:%02x:%02x ", (hour), minute, second);
    mylcd_string(0,0,buffer);
    RTC_Read_Calendar(3);    /* Read calendar with day address i.e location is 3 */
    sprintf(buffer, "%02x/%02x/%02x  ", date,month, year);
    mylcd_string(0, 1, buffer);
    reset_task(5);
    task_timers[5] = 50;    //run twice per second
}

void task6(void)
{

reset_task(6);
}

void task7(void)
{

reset_task(7);
}

//call this routine to initialize all peripherals
void init_devices(void)
{
    //stop errant interrupts until set up
    cli(); //disable all interrupts
    DDRA = 0x00;//for temperature sensor
    DDRB = 0xff;//outputs for lcd
    PORTB = 0x00;
    PORTC = 0x00; // for rtc chip ds1307
    DDRC  = 0x00;
    PORTD = 0x0f;    //pull-up enables for 3 pushbuttons
    DDRD  = 0xf0;    //2 o/p for relays, 1 o/p for LED, 1 o/p for TXD and 3 i/p for pushbuttons
	lcd_init(LCD_DISP_ON);
	timer_0_init();
	debounce_init();

 sei(); //re-enable interrupts
 //all peripherals are now initialized
}
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer_0_init(void)
{
 TCCR0 = 0x00; //stops the counter
 TCNT0 = 0x00; //set count //initializes counter
 TCCR0 = (1 << WGM01) | (1 << CS00) | ( 1<<CS02); //CTC mode
 OCR0 = 0x9C; // initializes value to be compared
 TCCR0 = 0x05; //starts the  timer
}

ISR(TIMER0_COMP_vect)       //make sure this is correct - the compiler will complain if it's not
{
 //TIMER0 has overflowed
     tick_flag = 1;
     debounce();
}

Below is the picture of the circuit I have modified according to JIM.

Modified Circuit

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are missing my point.

 

TCCR0 = (1 << WGM01) | (1 << CS00) | ( 1<<CS02);
OCR0 = 0x9C;
TCCR0 = 0x05;

Do you realize that the first write to TCCR0 will have virtually no effect since you write 5 afterwards?

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

What I find frustrating is that I spent the time to read the mega32 datasheet and write code for you - only for you to ignore it then complain things don't work for you. This is what I wrote for you -

//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer0_init(void)
{
  TCCR0  = 0; //stop
  OCR0A = 77;   //my guess is you're using 8MHz. Change to suit the actual clock rate
  TCCR0 = (1<<WGM01) | (1<<CS0) | (1<<CS2) //start timer

  TIMSK |= (1<<OCIE0);
}

Your random approach to the problem clearly isn't working. Understand that you are dealing with complex things - the simplest mistake could have significant consequences. Work step by step and add features to your code. Test at each step.

 

I suggested you try my flashing led example - clearly you didn't. Now you are wasting everyone's time trying to backtrack.

 

Here's a little list of the issues:

1. you didn't initialise the lcd

2. the timer is not initialised correctly

3. interrupts not initialised correctly

4. because the timer and interrupts aren't working, nothing gets printed to the lcd

 

The fatal flaw in your thinking is you expect many things to work. since you have many defects, the problem becomes intractable. 

When you initialise the lcd, print something to it - if you get something on the lcd you know you've got that far. Had you done this, then you would have probably come to the conclusion that the timer isn't working and then concentrate your efforts there. Had you run my led example, you would've already solved that problem. There's no magic or genius involved - just simple steps.

Last Edited: Sat. Dec 7, 2019 - 09:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:

3.

Brian Fairchild wrote:
You still haven't shown us any code that initialises the LCD.

Well as I have stated above(#1) I am using peter fluery's library as my lcd basis you can check out the initialization code in the library I have actually initialized the lcd correctly according to the library.

 

But have you configured the library correctly?

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As usual I would type a long message but as that wastes a lot of your (community's) time I will not do this as this message is not technical and hence I deem this not correct to share my problems(personal)

with the community but you(Kartman) has spoken for all of you, he is absolutely correct that the projects I have undertook are not able to run by my actions which are identical of a child struggling with his puzzle pieces (hit and trial method). Let me workout on this for a couple of days maybe a week or so and I promise I will be back with some results you all then can evaluate the code what you all should be doing instead of writing codes for beginners(sometimes you can but not all the time).Sorry for ignoring the community's efforts. 

Kartman wrote:
Test at each step.

The most important advice you won't get on any website ,thanks for that let me try this with  the way it's done.

Thank you all, gimme time and I'll be back hence I am not closing the discussion here ,wait for me. Really appreciated that you have responded to my cries.

YOU CAN LEARN TO CODE BUT YOU STILL NEED TO KNOW HOW IT'S DONE which I think is the main problem for me I don't know how to synchronize code blocks all together, thanks for advising me .

smiley

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

(a).Thanks I thought I would piss someone off by questioning them , well the lcd works means that it's lighted up but doesn't give anything(it gives only a blank screen).

For now, the strong advice, is to completely forget about multitasking, ADC, timers, button, etc...put all that stuff & code in a box in the closet for now.  ONLY use & modify Flurey's code (do not add a whole bunch of code with it), until your LCD works and displays:

Hi FREAKS

AVR ROCKS

 

Only after you have that LCD up your sleeve, then move on to buttons, then ADC, TIMERS, multitasking, etc.  Since the LCD will be working, you can use it to show things to help you debug all the rest (such as tracking states in a state machine)

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sun. Dec 8, 2019 - 12:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Guys I am back with something! Please tell me is that the way to do it . Kartman please tell me how can I make more tasks running simultaneously, because I have tried to use my Rtc and temperature code with the code below but it doesn't work quite well shows a non-responsive screen (the seconds doesn't change)can you please help me here.

Modified Circuit

Both the leds works blinks at different rate as well as the lcd I have tried to induce the rtc code but it shows unresponsiveness(seconds doesn't change) shown below:-

Screen output

What I am doing wrong?The code is below:-

//
//	Co-operative multitasking framework tutorial code
//	(c)Russell Bull 2010. Free for any use.
//	Code built for a Mega168 @ 16MHz
//
//	flash two outputs (PORTB.4,PORTB.5) at different speeds - blinky#2.
//

#include  <avr/io.h>
#include  <util/delay.h>
#include  <avr/interrupt.h>
#include  <avr/eeprom.h>
#include  <avr/pgmspace.h>
#include  "lcd.h"

void init_devices(void);
void timer0_init(void);
void reset_task(char tsk);
void set_task(char tsk);
void task_dispatch(void);
void task0(void);
void task1(void);
void task2(void);
void task3(void);
void task4(void);
void task5(void);
void task6(void);
void task7(void);

#define NUM_TASKS 8
char task_bits = 0;  /* lsb is hi priority task */
volatile char tick_flag = 0;    /* if non-zero, a tick has elapsed */
unsigned int task_timers[NUM_TASKS]={0,0,0,0,0,0,0,0};                  /* init the timers to 0 on startup */
static const PROGMEM char bit_mask[]={1,2,4,8,16,32,64,128};            /* value -> bit mask xlate table */

int main(void)
{ 

  init_devices();
//
//	start at least one task here
//
set_task(7);	//task7 runs
set_task(6);	//task6 runs
set_task(0);    //DO I HAVE TO INITIALIZE EACH AND EVERY TASK HERE?

//      main loop 

  while(1)
    {
    if (tick_flag)
      {
      tick_flag = 0;
	  task_dispatch();              // well....
	  }
	}
  return 0;
}
//
//	a task gets dispatched on every tick_flag tick (10ms)
//
void task_dispatch(void)
{
  /* scan the task bits for an active task and execute it */

  char task;

/* take care of the task timers. if the value ==0 skip it
	else decrement it. If it decrements to zero, activate the task associated with it */

  task=0;
  while (task < NUM_TASKS )
    {
    if (task_timers[task])
	   {
  	   task_timers[task]--;            /* dec the timer */
	   if (task_timers[task] == 0 )
	   		{
	    	set_task(task); /* if ==0 activate the task bit */
			}
	   }
    task++;
    }

  task = 0; /* start at the most significant task */
  while (task <= NUM_TASKS )
    {
	  if ((task_bits & pgm_read_byte(&bit_mask[task])))
	  		{
	  		break; /* if activate task found..*/
			}
      task++;         /* else try the next one */
    }
  switch(task)            /* if task bit is active..execute the task */
    {
    case 0:
      task0();
      break;
    case 1:
      task1();
      break;
    case 2:
      task2();
      break;
    case 3:
      task3();
      break;
    case 4:
      task4();
      break;
    case 5:
      task5();
      break;
    case 6:
      task6();
      break;
    case 7:
      task7();
      break;
    default:
      break;                  /* no task was active!! */
    }
}

// enable a task for execution
void set_task(char tsk)
{
  task_bits |= pgm_read_byte(&bit_mask[tsk]);       /* sets a task bit */
}
// disable a task from executing
void reset_task(char tsk)
{
  task_bits &= (~pgm_read_byte(&bit_mask[tsk]));  /* resets a task bit */
}

void task0(void)
{
	lcd_string(0, 0, "HI FREAKS");
	lcd_string(1, 0, "AVR ROCKS");
	task_timers[0] = 50;
    reset_task(0);
}
void task1(void)
{
  reset_task(1);
}
void task2(void)
{
  reset_task(2);
}
void task3(void)
{
  reset_task(3);
}
void task4(void)
{
  reset_task(4);
}
void task5(void)
{
  reset_task(5);
}
//
//	flash PORTB.4 at 2hz
//
void task6(void)
{
PORTD ^= (1<<4);
task_timers[6] = 50;

reset_task(6);
}
//
//	flash PORTB.5 at 1hz
//
void task7(void)
{
PORTD ^= (1<<5);
task_timers[7] = 20;		//every 500ms
reset_task(7);
}
//call this routine to initialize all peripherals
void init_devices(void)
{
	lcd_init(LCD_DISP_ON);
 //stop errant interrupts until set up
 cli(); //disable all interrupts

 DDRD = 0x30;	//port 4 & 5 as outputs
 DDRB = 0xff;//outputs for lcd
 PORTD = 0x0f;    //pull-up enables for 3 pushbuttons
 DDRD  = 0xf0;    //2 o/p for relays, 1 o/p for LED, 1 o/p for TXD and 3 i/p for pushbuttons

 timer0_init();

 MCUCR = 0x00;
 TIMSK = 0x02; //timer 0 interrupt sources

 sei(); //re-enable interrupts
 //all peripherals are now initialized
}
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 TCNT0 = 0x00; //set count
 TCCR0 = 0x02;	//CTC mode
 OCR0 = 0x9C;
 TCCR0 = 0x05; //start timer
}

ISR(TIMER0_COMP_vect)
{
 //TIMER0 has overflowed
 	tick_flag = 1;
}

 

Thanks for the help I was able to run this code.smileyPlease help me interface the RTC and the temperature sensor with the help of this code.

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 TCNT0 = 0x00; //set count
 TCCR0 = 0x02;	//CTC mode
 OCR0 = 0x9C;
 TCCR0 = 0x05; //start timer
}

How many times do we need to tell you there is a problem in this code?

You touch TCCR0 too many times.

Besides, didn't I write specific code for the mega32 for you??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh man this is not happening, I had actually used the older version of the code to post here, I am extremely sorry as you have done it for me here is the update that I have done in this block I think it's correct(doesn't the OCR0A should be OCR0 in case of my m32?), It works well the timing of the leds shows it's perfect, Thanks Kartmansmiley, once again.

void timer0_init(void)
{
	TCCR0  = 0; //stop
	OCR0 = 77;   //my guess is you're using 8MHz. Change to suit the actual clock rate
	TCCR0 = (1<<WGM01) | (1<<CS00) | (1<<CS02); //start timer
	TIMSK |= (1<<OCIE0);
}

I have tried to initialize more tasks rather than just showing text on the lcd but it hangs what could be the problem?.

I am extremely sorry for my acts(mistakes)that I am doing which I am not supposed to do.!

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
I have tried to initialize more tasks rather than just showing text on the lcd but it hangs what could be the problem?.

How could I possibly know without seeing any code? 

 

If you back up a bit, what have you got working so far?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Soo inconvenient of me I don't know what's wrong with me here is what I have,

//
//	Co-operative multitasking framework tutorial code
//	(c)Russell Bull 2010. Free for any use.
//	Code built for a Mega168 @ 16MHz
//
//	flash two outputs (PORTB.4,PORTB.5) at different speeds - blinky#2.
//

#include  <avr/io.h>
#include  <util/delay.h>
#include  <avr/interrupt.h>
#include  <avr/eeprom.h>
#include  <avr/pgmspace.h>
#include  <stdio.h>
#include  "I2C_Master_H_file.h"
#include  "lcd.h"

void init_devices(void);
void timer0_init(void);
void reset_task(char tsk);
void set_task(char tsk);
void task_dispatch(void);
void task0(void);
void task1(void);
void task2(void);
void task3(void);
void task4(void);
void task5(void);
void task6(void);
void task7(void);

#define NUM_TASKS 8
char task_bits = 0;  /* lsb is hi priority task */
volatile char tick_flag = 0;    /* if non-zero, a tick has elapsed */
unsigned int task_timers[NUM_TASKS]={0,0,0,0,0,0,0,0};                  /* init the timers to 0 on startup */
static const PROGMEM char bit_mask[]={1,2,4,8,16,32,64,128};            /* value -> bit mask xlate table */
//--------------------------------------------------------------------------------------------------------------
#define DS1307_WRITE_ADDR	0xD0	/* Define RTC DS1307 slave write address */
#define DS1307_READ_ADDR	0xD1	/* Make LSB bit high of slave address for read */
int second,minute,hour,day,date,month,year;
//--------------------------------------------------------------------------------------------------------------
#define DEGREE_SYMBOL 0xdf
//---------------------------------------------------------------------------------------------------------------
void RTC_Read_Clock(char read_clock_address)
{
	I2C_Start(DS1307_WRITE_ADDR);/* Start I2C communication with RTC */
	I2C_Write(read_clock_address);	/* Write address to read */
	I2C_Repeated_Start(DS1307_READ_ADDR);/* Repeated start with device read address */

	second = I2C_Read_Ack();	/* Read second */
	minute = I2C_Read_Ack();	/* Read minute */
	hour = I2C_Read_Nack();		/* Read hour with Nack */
	I2C_Stop();			/* Stop i2C communication */
}

void RTC_Read_Calendar(char read_calendar_address)
{
	I2C_Start(DS1307_WRITE_ADDR);
	I2C_Write(read_calendar_address);
	I2C_Repeated_Start(DS1307_READ_ADDR);

	day = I2C_Read_Ack();		/* Read day */
	date = I2C_Read_Ack();		/* Read date */
	month = I2C_Read_Ack();		/* Read month */
	year = I2C_Read_Nack();		/* Read the year with Nack */
	I2C_Stop();			/* Stop i2C communication */
}

void ADC_Init(){
	DDRA = 0x00;	        /* Make ADC port as input */
	ADCSRA = 0x87;          /* Enable ADC, with freq/128  */
	ADMUX = 0x40;           /* Vref: Avcc, ADC channel: 0 */
}

int ADC_Read(char channel)
{
	ADMUX = 0x40 | (channel & 0x07);   /* set input channel to read */
	ADCSRA |= (1<<ADSC);               /* Start ADC conversion */
	while ((ADCSRA & (1<<ADSC)));     /* Wait until end of conversion by polling ADC interrupt flag */
	return ADCW;                       /* Return ADC word */
}

int main(void)
{ 

  init_devices();
//
//	start at least one task here
//
set_task(7);	//task7 runs
set_task(6);	//task6 runs
set_task(0);   

//      main loop 

  while(1)
    {

    if (tick_flag)
      {
      tick_flag = 0;
	  task_dispatch();              // well....
	  }
	}
  return 0;
}
//
//	a task gets dispatched on every tick_flag tick (10ms)
//
void task_dispatch(void)
{
  /* scan the task bits for an active task and execute it */

  char task;

/* take care of the task timers. if the value ==0 skip it
	else decrement it. If it decrements to zero, activate the task associated with it */

  task=0;
  while (task < NUM_TASKS )
    {
    if (task_timers[task])
	   {
  	   task_timers[task]--;            /* dec the timer */
	   if (task_timers[task] == 0 )
	   		{
	    	set_task(task); /* if ==0 activate the task bit */
			}
	   }
    task++;
    }

  task = 0; /* start at the most significant task */
  while (task <= NUM_TASKS )
    {
	  if ((task_bits & pgm_read_byte(&bit_mask[task])))
	  		{
	  		break; /* if activate task found..*/
			}
      task++;         /* else try the next one */
    }
  switch(task)            /* if task bit is active..execute the task */
    {
    case 0:
      task0();
      break;
    case 1:
      task1();
      break;
    case 2:
      task2();
      break;
    case 3:
      task3();
      break;
    case 4:
      task4();
      break;
    case 5:
      task5();
      break;
    case 6:
      task6();
      break;
    case 7:
      task7();
      break;
    default:
      break;                  /* no task was active!! */
    }
}

// enable a task for execution
void set_task(char tsk)
{
  task_bits |= pgm_read_byte(&bit_mask[tsk]);       /* sets a task bit */
}
// disable a task from executing
void reset_task(char tsk)
{
  task_bits &= (~pgm_read_byte(&bit_mask[tsk]));  /* resets a task bit */
}

void task0(void)
{
	char Temperature[10];
	float celsius;
	char buffer[40];

	RTC_Read_Clock(0);	/* Read clock with second add. i.e location is 0 */
	sprintf(buffer, "%02x:%02x:%02x ", hour, minute, second);
	lcd_string(0,0,buffer);

	RTC_Read_Calendar(3);	/* Read calendar with day address i.e location is 3 */
	sprintf(buffer, "%02x/%02x  ", date,month);
	lcd_string(0, 11, buffer);

	lcd_string(1, 0,"TEMPERATURE");
	celsius = (float)ADC_Read(0)*4.88 / 10.0;
	sprintf(Temperature,"%d%cC  ", (int)celsius, DEGREE_SYMBOL);
	lcd_string(1,12,Temperature);

	reset_task(0);
	task_timers[0] = 50; // I tried to change this value to 100 so that rtc can refresh the display every second but to no use .
}
void task1(void)
{

  reset_task(1);
}
void task2(void)
{
  reset_task(2);
}
void task3(void)
{
  reset_task(3);
}
void task4(void)
{
  reset_task(4);
}
void task5(void)
{
  reset_task(5);
}
//
//	flash PORTB.4 at 2hz
//
void task6(void)
{
PORTD ^= (1<<4);
task_timers[6] = 50;

reset_task(6);
}
//
//	flash PORTB.5 at 1hz
//
void task7(void)
{
PORTD ^= (1<<5);
task_timers[7] = 20;		//every 500ms
reset_task(7);
}
//call this routine to initialize all peripherals
void init_devices(void)
{
	lcd_init(LCD_DISP_ON);
 //stop errant interrupts until set up
 cli(); //disable all interrupts

 DDRC  = 0x00;
 PORTC = 0x00; // for rtc chip ds1307

 DDRA = 0x00; // for temperature sensor

 DDRB = 0xff;//outputs for lcd

 PORTD = 0x0f;    //pull-up enables for 3 pushbuttons
 DDRD  = 0xf0;    //2 o/p for relays, 1 o/p for LED, 1 o/p for TXD and 3 i/p for pushbuttons

 timer0_init();

 MCUCR = 0x00;
 TIMSK = 0x02; //timer 0 interrupt sources

 sei(); //re-enable interrupts
 //all peripherals are now initialized
}
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer0_init(void)
{
	TCCR0  = 0; //stop
	OCR0 = 77;   //my guess is you're using 8MHz. Change to suit the actual clock rate
	TCCR0 = (1<<WGM01) | (1<<CS00) | (1<<CS02); //start timer
	TIMSK |= (1<<OCIE0);
}

ISR(TIMER0_COMP_vect)
{
 //TIMER0 has overflowed
 	tick_flag = 1;
}

 Until I add the rtc and temperature code,  lcd and leds go hand in hand simultaneously(as you can see above works greatyes) but now(after adding the code) :-

1.Display shows unresponsiveness , seconds doesn't change.

2.The temperature readings are also missing.

I think there is some kind of timing issue that I am facing here is there a clash of tasks that I am facing.?

Modified Circuit

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your description is confusing. Describe what works and what doesn't. Step by step.

 

You say the lcd and the leds go hand in hand - what does that mean? From what I can see if you remove the rtc and temperature code, nothing else talks to the lcd, so how do you know the lcd works?

 

if you comment out this line 

set_task(0); 

do the leds work?

does the lcd work?

How do you prove this?

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have proteus. This has a number of virtual instruments. Ask yourself how you could use these to show what is working and what is not? Hint - toggle port pins in critical sections of the code. Use the virtual oscilloscope to 'view' these.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I can explain, There are two conditions here:-

 

Condition 1. When I have haven't connected the rtc and temperature sensor :-

>> leds and lcd works as you can see in the picture in(#23)the code and picture are there to prove it, leds also work well, both flashing at different rates.

 

Condition 2. When I have connected the rtc and the temperature sensor:-

>>leds have stopped flashing

>>lcd shows the intended date and time from the rtc but it doesn't refresh(seconds doesn't change)

>>also temperature readings are also missing.

You can see what happened after I have connected both of these in (#27)

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

task0 has many lines of code. Narrow down to the line of code that causes the problem. You are also trying to get both the temp sensor and rtc working at the same time - how do you know which one might be causing the problem? take one step at a time. Add small amounts of code then test. If something doesn't work, then there are less possible causes. You should then be able to tell me what line of code causes a problem. Then we can look closer. At the moment there's say 20 lines of code that each could have a defect. How is any human going to solve 20 problems at once?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Add small amounts of code then test.
@Anshumaan, This is the whole reason for writing "modular" C code. You don't write 2,000 lines of code, program it into the micro then ask "well why doesn't that all work?". You work on isolated 10-20  line sections, one at a time, do whatever is necessary to prove that small part works faultlessly then from then on you treat it as a "black box". Think of building a house on foundations of even building a structure from lego bricks. You work on a small part, ensure it is solid and stable and then use that part as the basis to build the next part on top.

 

Just throwing all the code together and then trying to work out why the overall solution does not work as intended is a terrible approach. You may find it difficult to locate the sub-section that is actually wrong or, worse than that, you have have multiple problems in different areas or worse still, some problems that currently mask others.

 

I would work on you LCD stuff away from everything else, work on the RTC stuff away from everything else, temperature sensor away from everything else, LED support away from everything else. Give each module inputs/outputs/control functions that give access to all the features you may require from them ("readTempSensor(), printTextOnLcd() etc) then your final job becomes "system integration" where you wire all the proven modules together. You don't need to worry about any individual module mis-behaving as you have already proven each to be totally reliable in isolation.

 

Having a tool like Proteus should make this kind of thing even easier as it's very easy to test something like temperatureSensor() in isolation without needing output functions like LCD to be working at that time as the inspection tools in the debugger let you see what it is doing anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Narrow down to the line of code that causes the problem.

Thank you very much Kartman again. I have isolated the rtc code and the temperature sensor code in individual task blocks and rtc works flawlessly , thanks for you help.

But the temperature sensor doesn't work let me work onto that myself .smileyThanks again really appreciated your help.

 

clawson wrote:

You work on a small part, ensure it is solid and stable and then use that part as the basis to build the next part on top.

Yes sir,  the same is being said by Kartman and avrcandies many times I don't know why I am not following their advice. It could be because I grew impatient over time on the fact that I can't run something .As I am addicted to AVRs and hence even a small failure makes me impatient I am try to hush things then overlooking even the minor important details and hence a multitude of problem arises. Thanks for helping me soo much, let me work with the way everyone has asked me to do I will be back most probably with a working model or a system integration problem only, the rest I will try to do it myself.Thanks Clawson(Your name Cliff's ?) for making me realize that my way of doing it, is not correct.smiley .

Thanks everyone. 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Anshumaan wrote:
(Your name Cliff's ?)
It is. You're welcome.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone once again. I have returned although it took me 8 days but I am happy with what I have achieved till now. Here is what I am able to do:

1. I was able to run the Kartman's Multitasking code very well thanks Kartman for such a wonderful code.

2. RTC and temperature sensors work well , even others sensors worked well simultaneously with these two.I had used the code on the hardware and it worked well.I would love to show the hardware of mine but sorry I had dismantled it earlier due to some shortage that I had faced. Don't worry but I will show you.

3.The switches are now fully debounced.They work perfectly.

Below is the code:-smiley

#include  <avr/io.h>
#include  <util/delay.h>
#include  <avr/interrupt.h>
#include  <avr/eeprom.h>
#include  <avr/pgmspace.h>
#include  <stdio.h>
#include  "debounce.h"
#include  "lcd.h"
#include  "RTC_routines.h"
#include  "i2c_routines.h"

void init_devices(void);
void timer0_init(void);
void reset_task(char tsk);
void set_task(char tsk);
void task_dispatch(void);
void task0(void);
void task1(void);
void task2(void);
void task3(void);
void task4(void);
void task5(void);
void task6(void);
void task7(void);

#define NUM_TASKS 8
char task_bits = 0;  /* lsb is hi priority task */
volatile char tick_flag = 0;    /* if non-zero, a tick has elapsed */
unsigned int task_timers[NUM_TASKS]={0,0,0,0,0,0,0,0};                  /* init the timers to 0 on startup */
static const PROGMEM char bit_mask[]={1,2,4,8,16,32,64,128};            /* value -> bit mask xlate table */
//--------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------
#define DEGREE_SYMBOL 0xdf
//---------------------------------------------------------------------------------------------------------------

void ADC_Init(){
	DDRA = 0x00;	        /* Make ADC port as input */
	ADCSRA = 0x87;          /* Enable ADC, with freq/128  */
	ADMUX = 0x40;           /* Vref: Avcc, ADC channel: 0 */
}

int ADC_Read(char channel)
{
	ADMUX = 0x40 | (channel & 0x07);   /* set input channel to read */
	ADCSRA |= (1<<ADSC);               /* Start ADC conversion */
	while ((ADCSRA & (1<<ADSC)));     /* Wait until end of conversion by polling ADC interrupt flag */
	return ADCW;                       /* Return ADC word */
}

int main(void)
{ 

  init_devices();
//
//	start at least one task here
//

set_task(1);    //rtc show
set_task(2);    //lm 35 sensor
set_task(3);    //button_1
set_task(4);    //button_2
set_task(7);   //flasher

//      main loop 

  while(1)
    {

    if (tick_flag)
      {
      tick_flag = 0;
	  task_dispatch();              // well....
	  }
	}
  return 0;
}
//
//	a task gets dispatched on every tick_flag tick (10ms)
//
void task_dispatch(void)
{
  /* scan the task bits for an active task and execute it */

  char task;

/* take care of the task timers. if the value ==0 skip it
	else decrement it. If it decrements to zero, activate the task associated with it */

  task=0;
  while (task < NUM_TASKS )
    {
    if (task_timers[task])
	   {
  	   task_timers[task]--;            /* dec the timer */
	   if (task_timers[task] == 0 )
	   		{
	    	set_task(task); /* if ==0 activate the task bit */
			}
	   }
    task++;
    }

  task = 0; /* start at the most significant task */
  while (task <= NUM_TASKS )
    {
	  if ((task_bits & pgm_read_byte(&bit_mask[task])))
	  		{
	  		break; /* if activate task found..*/
			}
      task++;         /* else try the next one */
    }
  switch(task)            /* if task bit is active..execute the task */
    {
    case 0:
      task0();
      break;
    case 1:
      task1();
      break;
    case 2:
      task2();
      break;
    case 3:
      task3();
      break;
    case 4:
      task4();
      break;
    case 5:
      task5();
      break;
    case 6:
      task6();
      break;
    case 7:
      task7();
      break;
    default:
      break;                  /* no task was active!! */
    }
}

// enable a task for execution
void set_task(char tsk)
{
  task_bits |= pgm_read_byte(&bit_mask[tsk]);       /* sets a task bit */
}
// disable a task from executing
void reset_task(char tsk)
{
  task_bits &= (~pgm_read_byte(&bit_mask[tsk]));  /* resets a task bit */
}

void task0(void)
{;

	reset_task(0);
}
void task1(void)
{
	uint8_t line2[]		= "                 ";

		RTC_read();
			sprintf(line2,"%02x/%02x/%02x  /%02x/%02x",  HOURS, MINUTES, SECONDS, DATE, YEAR);
			lcd_string(0, 0, line2);

  task_timers[1] = 50;
  reset_task(1);

}
void task2(void)
{
	char Temperature[10];
	float celsius;

	lcd_string(0, 1,"TEMPERATURE = ");
	celsius = (float)ADC_Read(0)*4.88 / 10.0;
	sprintf(Temperature,"%d%cC  ", (int)celsius, DEGREE_SYMBOL);
	lcd_string(14,1,Temperature);

	task_timers[2] = 100;    //run once per two seconds

  reset_task(2);
}
void task3(void)
{
	if (button_down(BUTTON1_MASK))
	{
		// Toggle PB0
		PORTD ^= 1<<PD7;
	}
	task_timers[3] = 50;
    reset_task(3);
}
void task4(void)
{
	if (button_down(BUTTON2_MASK))
	{
		// Toggle PB1
		PORTD ^= 1<<PD6;
	}
	task_timers[4] = 50;
  reset_task(4);
}
void task5(void)
{  

  reset_task(5);
}

void task6(void)
{

reset_task(6);
}

void task7(void)
{
PORTD ^= (1<<5);
task_timers[7] = 20;		//every 500ms
reset_task(7);
}
//call this routine to initialize all peripherals
void init_devices(void)
{
	lcd_init(LCD_DISP_ON);
	DDRC  = 0x00;
	PORTC = 0x00; // for rtc chip ds1307

	DDRA = 0x00; // for temperature sensor

	DDRB = 0xff;//outputs for lcd

	PORTD = 0x0f;    //pull-up enables for 3 pushbuttons
	DDRD  = 0xf0;    //2 o/p for relays, 1 o/p for LED, 1 o/p for TXD and 3 i/p for pushbuttons
	 //stop errant interrupts until set up
	 cli(); //disable all interrupts
	 ADC_Init();
	 timer0_init();
	 MCUCR = 0x00;
	 TIMSK = 0x02; //timer 0 interrupt sources
	 sei(); //re-enable interrupts
	 //all peripherals are now initialized
}
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer0_init(void)
{
	TCCR0  = 0; //stop
	OCR0 = 77;   //my guess is you're using 8MHz. Change to suit the actual clock rate
	TCCR0 = (1<<WGM01) | (1<<CS00) | (1<<CS02); //start timer
	TIMSK |= (1<<OCIE0);
	debounce_init();
}

ISR(TIMER0_COMP_vect)
{
 //TIMER0 has overflowed
 	tick_flag = 1;
	 debounce();
}

Thanks everyone really appreciate you guys. Above is the result of your precious guidance.

Now can I ask for another favour I want to add one more thing to the buttons:-

#>> If button is pressed then they should show a countdown on the lcd (say 3 minutes) and the output should remain ON for that period, then it should turn OFF after that time until button is pressed again and the cycle should continue.

I know this will require these things :-

1. Knowledge of how to acquire these much long delays(I know this).

2. How to create a countdown.(I am kinda confused in this part there are tons of options still I am not getting it)

3. How to put both of these under the button.

Please can someone advice me .smiley

 

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are a number of errors in your posted code. Fix these first. Things like 20 ticks equalling 500ms. If each tick is 10ms, then 20 times 10 does not equal 500. Your code is riddled with such silliness.

If you want a delay of 3 minutes, then have a task that runs every second and decrements a variable. The answer is already in the code you posted - but i suspect you haven't taken the time to work through and understand it. Do yourself a favour - spent time he time now or waste lots more later.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Things like 20 ticks equalling 500ms.

Thanks for the response I am sorry that this comment is still there it was not supposed to be.

 

Kartman wrote:
If you want a delay of 3 minutes, then have a task that runs every second and decrements a variable.

Oh. you are absolutely right I don't why this came into mind thanks for the trick let me try this. 

 

Kartman wrote:
but i suspect you haven't taken the time to work through and understand it. Do yourself a favour - spent time he time now or waste lots more later.

You are indeed correct here too how you do this I don't know. Actually I was busy doing some other chores like the countdown I am sorry that I have overlooked the fact that you need to completely understand the things you are dealing with and then go on with more .Thanks for the help and great advice let me check this. 

You guys are just like an angel to me .laugh

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is what I have done to implement the countdown under a button press. It works but is this the way to do it??

void task3(void)
{

	counting--;
	unsigned char countingbuffer[20];

	if(counting == 0)
	{
	   counting = 0;
	}
	else
	{
        itoa(counting, countingbuffer, 10);
		lcd_string(18, 2, countingbuffer);
	}

	task_timers[3] = 100;
    reset_task(3);
}
void task4(void)
{

	if (button_down(BUTTON1_MASK))
	{

		PORTD ^= 1<<PD6;
		task3();// I have not launched the task_3 independently.
	}
	task_timers[4] = 100;
  reset_task(4);
}

This code works except for the fact that it shows 90 instead of 09 when the countdown steps down from 10.

Also I am concerned about that problem which I am facing in reassigning of the counting variable I have used here,  I have reassigned to 0 but as the counting stops it shows itself as 25 on the lcd, What I am doing wrong?

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:
This code works except for the fact that it shows 90 instead of 09 when the countdown steps down from 10.

output two (or three) spaces to the LCD at the same location to clear the number, just before updating with new value, so as the number of digits change, you don't leave behind remnants of previous values. 

 

An alternative to itoa is printf and specify either leading blanks or leading zeros to your number with a fixed number of characters for the value)

 

Jim

Controlling integer width with printf

The %3d specifier is used with integers, and means a minimum width of three spaces, which, by default, will be right-justified:

printf("%3d", 0); 0
printf("%3d", 123456789); 123456789
printf("%3d", -10); -10
printf("%3d", -123456789); -123456789

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

Last Edited: Wed. Dec 18, 2019 - 08:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:
output two (or three) spaces to the LCD at the same location to clear the number, just before updating with new value, so as the number of digits change, you don't leave behind remnants of previous values. 

Oh so sweet of you this really worked very well.Thanks.

Can someone please see that why my reassignment doesn't work it always skips the zero and then either starts the counting to -1, -2 and soo on or stuck at 25 which I have never used in my code.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:

Can someone please see that why my reassignment doesn't work it always skips the zero and then either starts the counting to -1, -2 and soo on or stuck at 25 which I have never used in my code.

Because the code skips printing counting when counting is zero (and for some reason it also sets counting to zero when it's already zero).

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I gave you the hint that the answer was already in the code, this is what I meant:

    if (task_timers[task])
	   {
  	   task_timers[task]--;            /* dec the timer */
	   if (task_timers[task] == 0 )
	   		{
	    	set_task(task); /* if ==0 activate the task bit */
			}
	   }

This is where I implement an array of downcounters - one for each task. Rather than thinking in terms of code, think in terms of what you want to do- Here's how I would describe the above:

 

if the timer is not zero, then subtract one from the timer.

if the timer is now 0, then do something as the timer has elapsed.

 

 if (task_timers[task]) is shorthand for if (task_timers[task] != 0). I read it as " if task_timers is not zero". We do this because if the timer is already 0, subtracting one makes it roll around backwards for an unsigned variable or go negative if it is a signed variable. In your code you used itoa() which treats it as a signed variable - so that's why you got the negative value.

 

 

task_timers[task]--; /* dec the timer */ Again, we've used C's shorthand method of subtracting one. We could have easily written task_timers[task] = task_timers[task] -1; /* dec the timer */

 

 

Then we do this: if (task_timers[task] == 0 )

Our first test determined if the timer was non-zero, then we subtracted 1. Now, if the timer is 0, this means it was previously 1 so the timer has elapsed. This we call a 'change of state'. So the following code only gets executed when the timer has been running and has elapsed.

 

 

 

    if (task_timers[task])
	   {
  	   task_timers[task]--;            /* dec the timer */
	   } 
     else  //timer is 0
           { 
           set_task(task); /* if ==0 activate the task bit */ 
           }

If I had written the code above - what would happen? We count the timer down to 0, but if it is 0 we set the task to run. If the timer had not been loaded it would always be 0 and the task would always be set to run - we don't want this, so that's why we implemented the change of state.

 

 

As an aside, the task_timers are 16 bit variables. This means their maximum time is 2^16 times 10ms  = 655.36 seconds or around 10 minutes. We could make them uint32_t (32 bits) which would be 2^32 times 10ms = around 43million seconds or 716 thousand minutes or 12 thousand hours or 497 days. Normally you don't need delays that long, so using a 16 bit variable seems a reasonable choice.

 

 

You used itoa() to format for value. As Jim suggested, there's printf/sprintf functions that do a fancier job. The downside is that they can be large in code size. So, if you're short on code space, these may not be the best choice. I don't think you have that problem at the moment.

 

So rather than: 

itoa(counting, countingbuffer, 10);

 

you could

sprintf(countingbuffer,"%04u",counting);  //this pads the number with 0's so you get 4 digits

You also need to a

 

 

#include <stdio.h>

 at the top of your file.

 

 

Having two tasks to do essentially the same thing with two switches is wasteful. One task can do both and still have time to spare. The task is given 10ms to run, so you can do a bit of work in this time. I would suggest you have one task to read the rtc, one task to read the switches and do the timing and one task to manage the display. Having more than one task competing the the display creates the potential for clashes. Less tasks is better and make each task 'earn their keep'  ie: having a 10ms task do 5 microseconds of work is not necessarily a good idea.

 

 

One technique you should skill up on is 'finite state machines'. You can Google this term. I invented these when I was around 10 years old. I also invented PID. Unfortunately, later on I found out that these were not new ideas.

A state machine is rather simple - the system exists in 1 or more states. A counter is a simple example of a state machine. The states are 0,1,2,3,4,5... and the logic to move between these states is a simple increment. Where they come in handy is when you want to implement something that is a sequence of events. For example, you timer might have the following states:

 

0. wait for button press. if pressed, load timer with value, activate output, next state is 1.

1. decrement timer. if 0 then de - activate output, next state is 0

 

This is a simple state machine with two states. It can be easily expanded to do more complex sequences. The above would look something like this:

 


static uint8_t state = 0;
static uint16_t timer = 0;

switch(state)
{
    case 0: //wait for button press
        if (button_press)
            {
                PORTB |= (1<<PB5); //turn on output
                timer = TEN_SECONDS;
                state = 1;
                
            }
        break;
    
    case 1: //do timer
        if (timer)
            {
                timer--;
            }
        else
            {
                //timer has elapsed
                PORTB &= ~(1<<PB5); //output off
                state = 0;
            }
        break;
}

 

If you run this in a task every second, what will it do? Make sure you work through the code closely - it is simple, but it illustrates a very powerful concept.

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Anshumaan wrote:

Here is what I have done to implement the countdown under a button press. It works but is this the way to do it??

	counting--;
	unsigned char countingbuffer[20];

	if(counting == 0)
	{
	   counting = 0;
	}
	else
	{
        itoa(counting, countingbuffer, 10);
		lcd_string(18, 2, countingbuffer);
	}

This code works except for the fact that it shows 90 instead of 09 when the countdown steps down from 10.

Also I am concerned about that problem which I am facing in reassigning of the counting variable I have used here,  I have reassigned to 0 but as the counting stops it shows itself as 25 on the lcd, What I am doing wrong?

 

I see a problem here. More than one, even.

 

Quote:
Can someone please see that why my reassignment doesn't work it always skips the zero and then either starts the counting to -1, -2 and soo on or stuck at 25 which I have never used in my code.

 

 

What exactly do you think this does?

 

In particular, what exactly is the point of assigning 0 to counting if it is 0?

 

So, when you hit zero, you do nothing. When you haven't hit zero, you do the itoa thing. But you don't send the string out when you hit zero, only when you haven't hit zero, and then you continue counting down past zero. I have no idea what type "counting" is, so I don't know whether it goes negative or wraps around, but either way, the logic here is clearly not what you want, and I can't figure out what you intended with that.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you all very much for replying to my question. I am really sorry that I was not able to reply you people any earlier than this. The internet was down in my area for quite some days.Now let's come to the topic :- I was able to run the timer and the countdown related to the outputs too and thanks everyone for making that things possible. Below is your help and guidance and really very little of my work. Thank you guys. Screen output

Screen output

I don't know how to thank you guys all I can do now is to thank you here I wish I could see you genius people someday.smiley

Thanks again Kartman and others for helping me so much due to you people I have achieved what I intend to do. 

 

Kartman wrote:
If you run this in a task every second, what will it do? Make sure you work through the code closely - it is simple, but it illustrates a very powerful concept.

Thanks again Kartman for another useful concept I will sure use this in my other projects.... :-)

 

the_real_seebs wrote:
In particular, what exactly is the point of assigning 0 to counting if it is 0?
 

Ya, I did that myself by mistake in a hurry you know I have two problems :-

1. I am just learning things (Noob)

2. and another that I lose my mind when I am in a hurry or i am angry I have fixed that, Thanks for replying.

anshumaan kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry,no genius at work here. Just understanding fundamental concepts and process.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hehe. Oh I see. Even then, thankssmiley.

anshumaan kumar