首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何实现ESP8266 5 kHz脉宽调制?

如何实现ESP8266 5 kHz脉宽调制?
EN

Stack Overflow用户
提问于 2017-02-08 19:52:07
回答 2查看 9.9K关注 0票数 1

我需要实现一个5 kHz +/- 5%的脉宽调制输出。(可能是由于这个馈入的滤波电路,但我无法控制它。)

这可以通过ESP8266 (理想情况下使用NodeMCU)实现吗?

我意识到ESP8266的软件脉宽调制的最大频率为1 kHz,而sigma-Δ可用于实现固定频率约为300 kHz的脉宽调制。

那么有没有一种可靠的方法来实现5 kHz呢?我知道有些人尝试使用I2S外围设备进行波形输出,但我不确定它是否可以用于5 5kHz输出。

以前有没有人研究过类似的问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-05 14:54:15

您还可以使用具有可调时钟速度的硬件SPI接口。通过写入连续数据,输出波形显示在SCLK上。

我在使用MicroPython在ESP8266上用IC 74hc595创建骑士特效时,已经想出了上述问题(这确实很慢,因为它是一种脚本语言)。它的工作频率高达4 4MHz的SPI时钟速度。

缺点是,对于永久波形,您需要将数据永久写入MOSI (因为当SPI数据缓冲区为空时,SCLK上不再有信号)。

票数 1
EN

Stack Overflow用户

发布于 2017-02-15 04:52:23

基本代码是:

代码语言:javascript
运行
复制
#define  qap      2       //  Quick As Possible ... Duty cycle only 0, 50, 100%
#define  HFreq    5150
#define  pPulse   D2      // a NodeMCU/ESP8266 GPIO PWM pin
analogWriteRange(qap);    analogWriteFreq( HFreq );  analogWrite(pPulse, 1);    // start PWM

TL;DR刚刚做了一些粗略的benchamrk

代码语言:javascript
运行
复制
//     had HFreq=126400   with 75 KHz pulse at 80 MHz ESP clock, every 1 sec but proof of evidence lost 

名义上使用80 MHz时钟获得

代码语言:javascript
运行
复制
// 72.24 KHz  361178  2015061929
// 72.23 KHz  361163  2415062390
// 72.23 KHz  361133  2815062824

代码语言:javascript
运行
复制
// 141.52 KHz  353809  2009395076
// 141.54 KHz  353846  2409395627
// 141.52 KHz  353806  2809395946

160 MHz时钟

注意事项!

  1. 占空比范围为2!
  2. 此外,系统没有其他调节,因此串行IO等产生的其他时序伪影仍然存在。特别是由于WDT和WiFi最终出现的不稳定性。(无论如何,这大概只有在ESP8266处于压力和胁迫下才是一个问题。)

代码语言:javascript
运行
复制
// 141.50 KHz  353754  619466806
// 141.52 KHz  353810  1019467038
//     ...
// ad infinitum cum tempore finitum, infinitus est ad nauseum?
//     ...
// 141.54 KHz  353857  735996888
//
// ets Jan  8 2013,rst cause:4, boot mode:(1,7)
//
//wdt reset

当使用以下代码生成5 KHz方波信号时,上述考虑因素不是问题,也不会发生。

代码语言:javascript
运行
复制
// ------------  test results   for 80 MHz clock  --------------
//
//
//       PWM pulse test      
//
// F_CPU:          80000000L
// ESP8266_CLOCK:  80000000UL
// PWM "freq.":    5150
//
//
//   connect D1 to D2
//
//
//             raw     MPU     
// frequency  count   cycle  
// 0.00 KHz  1  407976267
// 4.74 KHz  9482  567976702
// 5.00 KHz  10007  727977137
// 5.00 KHz  10006  887977572
// 5.00 KHz  10006  1047978007
// 5.00 KHz  10007  1207978442
// 5.00 KHz  10006  1367978877
// 5.00 KHz  10006  1527979312
// 5.00 KHz  10007  1687979747
// 5.00 KHz  10006  1847980182
// 5.00 KHz  10006  2007980617
// 5.00 KHz  10007  2167981052
// 5.00 KHz  10006  2327981487
// 5.00 KHz  10006  2487981922
// 5.00 KHz  10007  2647982357  ...
//
//    crude testing for 5KHz signal
//          extracted from:
//                highest frequency / shortest period pin pulse generate / detect test
//
//     uses raw ESP8266 / NodeMCU V1.0 hardware primitive interface of Arduino IDE (no included libraries)
//
//     timing dependencies: WDT, WiFi, I2S, I2C, one wire, UART, SPI, ...
//
//  Arduino GPIO   16    5    4    0    2   14   12   13   15    3    1      0  1  2  3  4  5 ... 12 13 14 15 16 
//  NodeMCU D pin   0    1    2    3    4    5    6    7    8    9   10      3 10  4  9  2  1 ...  6  7  5  8  0 
//                  |    |    |    |    |    |    |    |    |    |    |                      
//    a           WAKE   |    |   F    Tx1   |    |   Rx2  Tx2  Rx0  Tx0             
//     k      (NO PWM or |    |    L   blue  |    |    |    |                               
//      a'    interrupt) |  S       A   *  H |  H |  H |    |                     * led's
//       s         red  S    D       S      S    M    S    H       
//                  *    C    A       H      C    I    I    C                    
//                        L    T              L    S    M    S   
//                         K    A              K    O    O              
//                                       └  -  -  -  - └----UART's----┘         
//                      └--I2C--┘            └-----SPI------┘
//
//  rules of engagement are obscure and vague for effects of argument values for the paramters of these functions:
//      analogWriteRange(qap);     analogWriteFreq( HFreq );              analogWrite(pPulse, 1);  
//
//    http://stackoverflow.com/questions/42112357/how-to-implement-esp8266-5-khz-pwm  
//
//   system #defines:  F_CPU  ESP8266_CLOCK
#define  pInt     D1          // HWI pin: NOT D0 ie. GPIO16 is not hardwared interrupt or PWM pin
#define  pPulse   D2          // PWM pulsed frequency source   ...  ditto D0  (note: D4 = blue LED)
#define  countFor 160000000UL 

#define  gmv(p)   #p          //  get macro value
#define  em(p)    gmv(p)      //  evaluate macro
#define  qap      2           //  minimal number of duty cycle levels (0, 50, 100% ) Quick As Possible ...
#define  HFreq    5150 //((long int) F_CPU==80000000L ? 125000 : 250000)        // ... to minimize time of a cycle period
                                     //   max values      ^   and   ^   found empirically
//     had HFreq=126400   with 75 KHz pulse at 80 MHz ESP clock, every 1 sec but proof of evidence lost
#define  infoTxt (String)                                                  \
                  "\n\n\t    PWM pulse test        "                        \   
                  "\n F_CPU:          " em(F_CPU)                          \
                  "\n ESP8266_CLOCK:  " em(ESP8266_CLOCK)                  \
                  "\n PWM \"freq.\":    " + HFreq + "\n"                   \
                  "\n\n   connect " em(pInt) " to " em(pPulse) "\n"        \  
                  "\n\n             raw     MPU   "                        \
                  "  \n frequency  count   cycle  "

long int oc=1, cntr=1;  
unsigned long int tc=0;
void hwISR(){ cntr++; }                                              // can count pulses if pInt <---> to pPulse
void anISR(){  tc=ESP.getCycleCount(); timer0_write( countFor + tc ); oc=cntr; cntr=1; }

void setup() {                                     // need to still confirm duty cycle=50%  (scope it or ...)
   noInterrupts(); 
      Serial.begin(115200); Serial.println(infoTxt);  delay(10);  // Serial.flush(); Serial.end(); // Serial timing?
      analogWriteRange(qap);     analogWriteFreq( HFreq );              analogWrite(pPulse, 1);    // start PWM
      pinMode( pInt,  INPUT );   attachInterrupt(pInt, hwISR, RISING);                             // count pulses
      timer0_isr_init();         timer0_attachInterrupt( anISR );       anISR();                   // 
   interrupts();
}

void loop() {  delay(10);     if (oc==0) return;  
               Serial.println((String)" "+(oc/1000.0*F_CPU/countFor)+" KHz  "+oc+"  "+tc);   oc=0;    }  
//
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42112357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档