A timer and interrupt system for the ESP8266
The current method of managing timing signals for Not-GRBL is by a "blink without delay" style of programming.
It is somewhat restrictive but it works.
This style of programming is also called "polling" and is basically the same a the "Ticker" library.
What is really needed is access to a hardware timer and an Interrupt Service Vector.
The ESP8266 provided a simple non-resetable up counter (the so called software timer) called timer0.
Basically this timer counts clock cycles (i.e. at 80 MHz).
Here is a bit of code the write my own "servo sweep":
#define servoPin D4
volatile int servoPulse=0;
volatile int servoAngle=90;
volatile unsigned long next;
void inline servoISR(void){
if (servoPulse==0) {
next=next+40000+889*servoAngle;
} else {
next=next+1560000-889*servoAngle;
}
timer0_write(next);
servoPulse=1-servoPulse;
digitalWrite(servoPin,servoPulse);
}
void setup()
{
// Servo initialisation (uses D4)
pinMode(D4,OUTPUT);
noInterrupts();
timer0_isr_init();
timer0_attachInterrupt(servoISR);
next=ESP.getCycleCount()+1000;
timer0_write(next);
interrupts();
// Serial.begin(9600);
// Serial.println();
}
void loop()
{
const int minAngle=16;
const int maxAngle=176;
const int midAngle=96;
static int servoDir=1;
delay(50);
// Next position
if (servoAngle>maxAngle) servoAngle=maxAngle;
if (servoAngle<minAngle) servoAngle=minAngle;
if (servoAngle==maxAngle) servoDir=-servoDir;
if (servoAngle==minAngle) servoDir=-servoDir;
servoAngle+=servoDir;
// Serial.println(servoAngle);
}
Here is the critical bit of code:
noInterrupts();
timer0_isr_init();
timer0_attachInterrupt(servoISR);
next=ESP.getCycleCount()+1000;
timer0_write(next);
interrupts();
What does it do?
- Initialises the timer
- Attach the interrupt service routine (ISR)
- Gets the current clock count and add 1000 clock cycle to it
- Tell the timer to call the ISR after 1000 clock cycles
It takes about 180 clock cycles to call the ISR.
Limitations
Other processes use the same timer and it has been reported that a 2 ms tick will crash the ESP6288 if you are using WiFi.
Other timers
There is also a timer1 (that needs investigation).
AlanX
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
Hello everybody!
Please let me ask a stupid question as to why timer0_write (ESP.getCycleCount () + 80000000L); // 80MHz == 1sec
(80MHz == 1sec?) Please direct, thanks everyone.
Are you sure? yes | no
Wow interesting, i was working on almost same but use os timer est_timer_arm_new in microseconds, and on 80Mhz able to pulse more than 100Khz, the problem is that it cannot alter the interval between interrupt, and the ets_timer_arm is to costly on cpu, so cannot be called inside the interrupt itself.
Your code is really great, cant wait to change my code using code like yours.
Are you sure? yes | no