Giter Site home page Giter Site logo

Comments (5)

khoih-prog avatar khoih-prog commented on May 12, 2024

You have the big WDT problem because you're using "time-consuming code" inside the ISR.

The best way to do inside the ISR is just to set a flag, then using the flag to run the actual "time-consuming code"

Have a look at the modified code hereafter and modify the time accordingly to your use case. I expand the time to just demonstrate the operation

1.Revised code to use "lean and mean" code inside ISR : setting just a flag

#include "ESP8266TimerInterrupt.h"

#ifndef LED_BUILTIN
#define LED_BUILTIN       2         // Pin D4 mapped to pin GPIO2/TXD1 of ESP8266, NodeMCU and WeMoS, control on-board LED
#endif

const int sinus[] = {  0, 20, 45, 89, 134, 178, 221, 265, 308, 350, 391, 432,
                       472, 512, 550, 587, 623, 658, 691, 723, 754, 784,
                       812, 838, 863, 886, 907, 927, 945, 961, 976, 988,
                       999, 1007, 1014, 1019, 1022, 1023, 1023, 1023
                    };
                                      
const int sinuslen = sizeof(sinus) / sizeof(sinus[0]);
const int sinusschrittzeit = 60;
const long sinusdauer = sinusschrittzeit * sinuslen;

int step = 0;
int direction = 1;

ESP8266Timer ITimer;

volatile bool startRunning  = false;

void runSinus(void)
{
  analogWrite(LED_BUILTIN, 1023   /*sinus[step]*/);
  Serial.print("step = ");
  Serial.print(step);
  Serial.print(", sinus = ");
  Serial.println(sinus[step]);
  //Serial.print(".");
  
  step += direction;
  
  if (step < 0) 
  {
    step = 0;
    direction = 1;
    ITimer.disableTimer();
    
    Serial.println("\nDisable ITimer");
  }
  
  if (step > sinuslen - 1) 
  {
    step = sinuslen - 1;
    direction = -1;
  }

  startRunning = false;
}

void ICACHE_RAM_ATTR TimerHandler(void)
{
  startRunning = true;
}

void setup()
{
  Serial.begin(115200);
  while (!Serial);

  pinMode(LED_BUILTIN, OUTPUT);

  // Interval in microsecs
  if (ITimer.attachInterruptInterval(1000L /*60L*/ * 1000L, TimerHandler))
  {
    ITimer.disableTimer();
    Serial.println("\n\nStarting  ITimer OK");
  }
  else
    Serial.println("\n\nCan't set ITimer correctly. Select another freq. or interval");
}

void loop()
{
  static unsigned long ticker = 0;

  if (startRunning)
  {
    runSinus(); 
  }

  if ( (ticker == 0) || (millis() - ticker > 60000 /*6000*/) )
  {
    step = 0;
    direction = 1;
    ticker = millis();
    ITimer.enableTimer();

    Serial.println("\nRestarting  ITimer");
  }
}

2. Terminal output


Starting  ITimer OK

Restarting  ITimer
step = 0, sinus = 0
step = 1, sinus = 20
step = 2, sinus = 45
step = 3, sinus = 89
step = 4, sinus = 134
step = 5, sinus = 178
step = 6, sinus = 221
step = 7, sinus = 265
step = 8, sinus = 308
step = 9, sinus = 350
step = 10, sinus = 391
step = 11, sinus = 432
step = 12, sinus = 472
step = 13, sinus = 512
step = 14, sinus = 550
step = 15, sinus = 587
step = 16, sinus = 623
step = 17, sinus = 658
step = 18, sinus = 691
step = 19, sinus = 723
step = 20, sinus = 754
step = 21, sinus = 784
step = 22, sinus = 812
step = 23, sinus = 838
step = 24, sinus = 863
step = 25, sinus = 886
step = 26, sinus = 907
step = 27, sinus = 927
step = 28, sinus = 945
step = 29, sinus = 961
step = 30, sinus = 976
step = 31, sinus = 988
step = 32, sinus = 999
step = 33, sinus = 1007
step = 34, sinus = 1014
step = 35, sinus = 1019
step = 36, sinus = 1022
step = 37, sinus = 1023
step = 38, sinus = 1023
step = 39, sinus = 1023
step = 39, sinus = 1023
step = 38, sinus = 1023
step = 37, sinus = 1023
step = 36, sinus = 1022
step = 35, sinus = 1019
step = 34, sinus = 1014
step = 33, sinus = 1007
step = 32, sinus = 999
step = 31, sinus = 988
step = 30, sinus = 976
step = 29, sinus = 961
step = 28, sinus = 945
step = 27, sinus = 927
step = 26, sinus = 907
step = 25, sinus = 886
step = 24, sinus = 863
step = 23, sinus = 838
step = 22, sinus = 812
step = 21, sinus = 784
step = 20, sinus = 754
step = 19, sinus = 723
step = 18, sinus = 691
step = 17, sinus = 658
step = 16, sinus = 623
step = 15, sinus = 587
step = 14, sinus = 550
step = 13, sinus = 512
step = 12, sinus = 472
step = 11, sinus = 432
step = 10, sinus = 391
step = 9, sinus = 350
step = 8, sinus = 308
step = 7, sinus = 265
step = 6, sinus = 221
step = 5, sinus = 178
step = 4, sinus = 134
step = 3, sinus = 89
step = 2, sinus = 45
step = 1, sinus = 20
step = 0, sinus = 0

Disable ITimer

Restarting  ITimer
step = 0, sinus = 0
step = 1, sinus = 20
step = 2, sinus = 45
step = 3, sinus = 89
step = 4, sinus = 134
step = 5, sinus = 178
step = 6, sinus = 221
step = 7, sinus = 265
step = 8, sinus = 308
step = 9, sinus = 350
step = 10, sinus = 391
step = 11, sinus = 432
step = 12, sinus = 472
step = 13, sinus = 512
step = 14, sinus = 550
step = 15, sinus = 587
step = 16, sinus = 623
step = 17, sinus = 658
step = 18, sinus = 691
step = 19, sinus = 723
step = 20, sinus = 754
step = 21, sinus = 784
step = 22, sinus = 812
step = 23, sinus = 838
step = 24, sinus = 863
step = 25, sinus = 886
step = 26, sinus = 907
step = 27, sinus = 927
step = 28, sinus = 945
step = 29, sinus = 961
step = 30, sinus = 976
step = 31, sinus = 988
step = 32, sinus = 999
step = 33, sinus = 1007
step = 34, sinus = 1014
step = 35, sinus = 1019
step = 36, sinus = 1022
step = 37, sinus = 1023
step = 38, sinus = 1023
step = 39, sinus = 1023
step = 39, sinus = 1023
step = 38, sinus = 1023
step = 37, sinus = 1023
step = 36, sinus = 1022
step = 35, sinus = 1019
step = 34, sinus = 1014
step = 33, sinus = 1007
step = 32, sinus = 999
step = 31, sinus = 988
step = 30, sinus = 976
step = 29, sinus = 961
step = 28, sinus = 945
step = 27, sinus = 927
step = 26, sinus = 907
step = 25, sinus = 886
step = 24, sinus = 863
step = 23, sinus = 838
step = 22, sinus = 812
step = 21, sinus = 784
step = 20, sinus = 754
step = 19, sinus = 723
step = 18, sinus = 691
step = 17, sinus = 658
step = 16, sinus = 623
step = 15, sinus = 587
step = 14, sinus = 550
step = 13, sinus = 512
step = 12, sinus = 472
step = 11, sinus = 432
step = 10, sinus = 391
step = 9, sinus = 350
step = 8, sinus = 308
step = 7, sinus = 265
step = 6, sinus = 221
step = 5, sinus = 178
step = 4, sinus = 134
step = 3, sinus = 89
step = 2, sinus = 45
step = 1, sinus = 20
step = 0, sinus = 0

Disable ITimer

....

from esp8266timerinterrupt.

holgerlembke avatar holgerlembke commented on May 12, 2024

Thanks for the very fast support. But your solution is not what I wanted to archive.

I wanted to create a isr-task that sets the pwm so I don't need the loop-stuff any more. As outlined in my example, I only want to start in the loop, then the timer isr shall walk through the sinus, each step lasting 60 ms. My code works fine without the analogWrite...

from esp8266timerinterrupt.

khoih-prog avatar khoih-prog commented on May 12, 2024

That's just an example to show you why you got WDT reset and what's wrong with your code.

You certainly can write a software timer to take care of the work, instead of relying on loop().

It's up to you now.

from esp8266timerinterrupt.

holgerlembke avatar holgerlembke commented on May 12, 2024

The real reason seems to be that both analogWrite()/PWM and your lib use Timer1. So both together simply don't work.

from esp8266timerinterrupt.

khoih-prog avatar khoih-prog commented on May 12, 2024

That's correct. But Timer0 is already used by WiFi and can not be used for PWM analogWrite() or creating unexpected WiFi issues and/or both.

One possible workaround, if analogWrite() usage is a must, is

  1. Using external i2C DAC
  2. using software PWM such as mentioned in this :

ESP8266 PWM REVISITED (AND REIMPLEMENTED)

The ESP8266 lacks any hardware support for PWM. Any ATtiny, PIC or any ARM Cortex M0 based SoC fares better in this regard, although the smallest SoCs may have only one or two channels.

As an alternative to hardware PWM it is possible to do PWM purely in software, typically assisted by interrupts from a hardware counter. For the ESP8266 a software PWM implementation is available in the SDK provided by Espressif, but it comes with several strings attached:

  1. It has a quite awkward API, the documentation lacks several important points open
  2. As any interrupt based implementation it is susceptible for glitches
  3. The duty cycle is limited to 90% maximum

THE MISSING MANUAL PARTS

The API has four important functions to control the PWM, as follows:

void pwm_set_duty(uint32 duty, uint8 channel)

Set the duty for a logical channel. One duty unit corresponds to 40ns. The maximum should be period / 40ns, but due to the implementation there is a fixed dead time of 100μs which limits the maximum duty to 90% when using a period of 1ms (i.e. a frequency of 1kHz).

void pwm_set_period(uint32 period)
Set the PWM period to period microseconds.

void pwm_start(void)
Needs to be called before any pwm_set_duty, pwm_set_period calls take any effect. Does some preparatory work needed for the interupts handler to do its job of toggling the GPIOs.

void pwm_init(uint32 period, uint32 * duty, uint32 pwm_channel_num, uint32 (*pin_info_list)[3])

duty points to an array of duty cycles, the number of array elements depends on the number of used channels. From the documentation it is not obvious if this is only needed for initial settings, if this is also accessed after the pwm_init call (e.g. ownership of the array is transfered) and if is save to pass NULL here.

pin_info_list points to an array of arrays. It better had been declared as an array of structs, each struct storing the configuration of a GPIO pin. As is, each 3-tuple stores:

  1. the name of the MUX configuration register as documented in the GPIO chapter of the SDK, see the PIN_FUNC_SELECT macro
  2. the name of the MUX setting, see GPIO SDK documentation
  3. the number of the GPIO from 0 to 15
    One 3-tuple is needed for each PWM channel/GPIO pin.

When the duty cycle > 90% is needed, just use analogWrite(pin,100) or even digitalWrite(pin, 1)

from esp8266timerinterrupt.

Related Issues (19)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.