# Calculate angle based on time of day not working

I have some code (relevant portions below) that I feel should work, but it doesn’t. It starts at 60 deg (I’m controlling a servo angle) at morning time and rotates slowly as time passes. It should be 120 deg at sunset but instead it’s capping out at like 104 deg and earlier in the day than it should.

Any help is appreciated! Thanks!

``````#include <avr/io.h>
#include <avr/interrupt.h>
#include "uart.h"

static volatile uint64_t milliseconds = 0;

int hour = 0;
int minute = 0;

int morning = 6;
int morning_min = 27;

int evening = 20;
int evening_min = 50;

void delay_ms(int ms)
{
uint64_t timestamp = milliseconds;
while(milliseconds - timestamp < ms);
}

int main(void)
{
initUART();

int now = (hour * 60) + minute;
int morn = (morning * 60) + morning_min;
int even = (evening * 60) + evening_min;

//setup if mid day
if (now >= morn && now <= even)
{
int denomenator = even - morn;
double numerator = now - morn;

double ratio = numerator / denomenator;

int angle = (ratio * 60) + 60;

OCR1A = angle;
}
else
{
OCR1A = 60;
}

char start = {0};
sprintf(start, "Startup-%02d:%02d-%d\n", hour, minute, OCR1A);
writeString(start);

DDRB |= (1 << PORTB1); //servo pin 6

//timer 0
OCR0A = 249; //1ms interval
TIMSK0 |= (1 << OCIE0A); //enable oputput compare interrupt
TCCR0A |= (1 << WGM01); //ctc
TCCR0B |= (1 << CS01) | (1 << CS00); //prescaler 64

//timer 1
TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10); // clear on match, fast pwm
TCCR1B |= (0 << WGM13) | (1 << WGM12) | (1 << CS12) | (0 << CS10); //1024 prescaler

sei(); //enable interrupts globally

while(1)
{
if((milliseconds % 10) == 0) {
minute++;

if(minute % 60 == 0)
{
minute = 0;
hour++;
}

if(hour % 24 == 0) { hour = 0; }

int now = (hour * 60) + minute;
if(now >= morn && now <= even)
{
int denomenator = even - morn;
double numerator = now - morn;

double ratio = numerator / denomenator;

int angle = (ratio * 60) + 60;

OCR1A = angle;
}

char message = {0};
sprintf(message, "%02d:%02d-%d\n", hour, minute, OCR1A);
writeString(message);
}
}
}

ISR(TIMER0_COMPA_vect)
{
milliseconds++;
}
``````

I guess this is for testing and in real life it would be milliseconds % 60000:

``````    while(1)
{
if((milliseconds % 10) == 0) {
minute++;

if(minute % 60 == 0)
``````

Correct, in practice it would be mod 60000, but for testing i did mod 10 to speed it up so i could see a whole 24 hour period in much less time

I think the problem is that you are not properly converting angles to servo pulse lengths. Servo pulses run from 1000 microseconds (0°) to 2000 microseconds (180°). You can't just use the angle value directly. The code doesn't have comments to show what the Timer1 clock rate is.