//___________________ Librairies & defines __________________//
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <stdio.h>
//RTC libs
#include <Wire.h>
#include <RTClib.h>
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz
#endif
// frequencion division
#define FREQ_DIV_8 (F_CPU / 8)
// #of ticks / millisec
#define MILLITICK (FREQ_DIV_8 * .001)
//______________________ Constants and global variables_______________//
const int divisions = 180; //a multiple of 60 to simplyfy the positioning
volatile byte LED [divisions+1]; //Array with positions where the leds should light up. in bytes so we can clock it directly in the portB register
// _____________period of the rotation of the disk
int period;
// ______________volatile so it will be accessible in the IRS routine
volatile int positionCounter = 0;
//____________RTC declareren
RTC_DS1307 RTC;
volatile boolean update; //variable to trigger update
void setup()
{
Serial.begin(115200);
Serial.println("serial is set");
//______________ RTC opzetten_____________//
// Wire.begin();
//RTC.begin();
delay(50);
Serial.println("rtc is set");
delay(50);
//________________ Set I/O ports ______________//
DDRL=255 ; //PL4 pin 45 as output for servo
DDRB=255; // pin 51 - 52 - 53 as ooutput for portb
DDRD=0;
Serial.println("IO is set");
delay(50);
//___________________Init Timers_______________________//
cli(); //disable timers
//********** PWM for Servo (ESC) ****************//
TCCR5A = (1 << COM5B1); // timer5: phase & frequency correct - pwm Clear OC1B on Compare Match
TCCR5B = (1 << WGM53) | (1 << CS51); //prescaler 8
ICR5 = 20000; // 20ms
OCR5B= 1500; // 1.5ms
Serial.println("servo is set");
delay(50);
//*************** Timers for disk position *****************//
// setup timer0 - 8bit, --> to drive the leds
TCCR2A = 0;
TCCR2B = 0;
// select CTC mode: clear timer on compare match mode
TCCR2A = (1<< WGM21);
// select prescaler clk / 8
TCCR2B= (1<< CS21);
// enable compare interrupt
TIMSK2 = (1<<OCIE2A);
// setup timer1 - 16bit to count the rotations and calculate the period
TCCR3B = 0;
TCCR3A = 0; // A1 registering p134
// select prescaler clk / 8
TCCR3B=(1<< CS31);
// reset timer
TCNT3 = 0;
// enable overflow interrupt
TIMSK3=(1<< TOIE3);
Serial.println("timer1 is set");
delay(50);
// stel PIN2( arduino D-input) falling edge interrupt
EICRA |= _BV(ISC21);
EIMSK |= _BV(INT2);
Serial.println("int2 is set");
delay(50);
// set the rotational period to 0
period = 0;
// setup timer3 - 16bit, --> to drive time keeping function
TCCR4A = 0;
TCCR4B = 0;
// select CTC mode: clear timer on compare match mode
TCCR4A = (1<< WGM41);
// select prescaler clk / 1024
TCCR4B= (1<< CS40)|(1<<CS42);
// enable compare interrupt
TIMSK4 = (1<<OCIE4A);
OCR4A=6250; //400ms
Serial.println("timer4 is set");
delay(50);
sei(); //reenable interrupts
Serial.begin(9600);
Serial.println("timers are set");
delay(50);
for(int i =0; i<divisions;i++){ //Set all bytes in the array to zero
LED[positionCounter]=0;
}
Serial.println("array is empty");
//Getting out of settings mode of the ESC & Testing leds
PORTB=0b00000001;
_delay_ms(5000);
PORTB=0b00000010;
OCR5B = 2000;
_delay_ms(2000);
PORTB=0b00000100;
OCR5B = 1000;
_delay_ms(2000);
OCR5B = 2000;
PORTB=0b00000000;
}
void loop()
{
if(update){
DateTime now = RTC.now();
int hours=now.hour()%12; //getting the time from 0 to 11 instead of 24 hours
int minutes= now.minute();
int seconds= now.second();
for(int i =0; i<divisions;i++){ //clear the whole array
LED[positionCounter]=0;
}
LED[hours*15] |= 4;
LED[minutes*3] |= 2;
LED[seconds*3] |= 1;
}
update=false;
}
ISR(INT2_vect) //Sensor interrupt routine
{
// period = nuber of ticks since last interrupt
period = TCNT3;
// if period < than to millis no rotation is possible --> discard value
// disk 7500 rpm --> 125rps -->8 millis /rotation
if(period <(2 * MILLITICK))
{
return;
}
//reset timer to zero
TCNT3 = 0;
//8bit timer0 generates an interrupt / division --> time between interrupts = period/divisions
TCNT2 = 0;
OCR2A = (period / divisions);
positionCounter = 25; // set position to 25. sensor is rotated 37° to the length axis of the disk.
}
ISR(TIMER2_COMPA_vect) { //timer interrupt routine
positionCounter = ((positionCounter + 1) % divisions); //position with modulo division
PORTB=LED[positionCounter]; //getting the led values of the current position and clocking them in the portB output register.
}
ISR(TIMER4_COMPA_vect) { //timer interrupt routine
update=true;
}
I always advise a little research before using a function. cli() does FAR more than disable timers. It stopps all interrupts. You can't do things that require interrupts while you have interrupts disabled. That means NO Serail.print() calls between cli() and sei().
I know. But wouldn't it resume everything else after sei(); ?
You are assuming that it gets there. If the serial buffer gets full, Serial.print() blocks until there is room in the buffer. Making room in the buffer requires shifting data out, which requires interrupts, which you have disabled.