Skip to content

Instantly share code, notes, and snippets.

@Tech-TX
Last active November 21, 2020 19:44
Show Gist options
  • Select an option

  • Save Tech-TX/572aab942d44638566e07036fe77a4c6 to your computer and use it in GitHub Desktop.

Select an option

Save Tech-TX/572aab942d44638566e07036fe77a4c6 to your computer and use it in GitHub Desktop.
generic test of the various PWM functions for the ESP8266 Arduino
// A simple test to exercise PWM, Tone and Servo functions, all controlled from the terminal.
// All PWM sources and WiFi are initially disabled, individually enabled from the terminal.
// If you have an RC filter on one of the PWM pins, you can read it at the A0 analog input.
// A 200-3K res & 10uf cap R-C work @ 500-40KHz PWM. Make sure your board supports 3.3V Ain!
//
// This code is released to the public domain with no guarantees whatsoever
// "If it breaks in half, you get to keep both halves." ~ George Carlin
#include <core_esp8266_waveform.h> // so we can independently disable PWM sources
#include <ESP8266WiFi.h> //the main WiFi routines
#include <ArduinoOTA.h> //the main OTA routines
#include <WiFiUdp.h> //low-level protocol used for OTA
#include <ESP8266mDNS.h> //needed for OTA from IDE
#include <Servo.h>
#include <polledTimeout.h>
const char* ssid = "your SSID";
const char* password = "your password/PSK";
IPAddress staticIP(192, 168, 0, abc); // parameters below are for your static IP address, if used
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns1(xxx, xxx, xxx, xxx);
IPAddress dns2(yyy, yyy, yyy, yyy);
const int CH1pin = 2; // D4, GPIO2 for PWM channel 1 (running if enabled & duty cycle > 0 or < 1023)
const int CH2pin = 5; // D1, GPIO5 for PWM channel 2 (inverse of channel 1 if enabled)
const int CH3pin = 0; // D3, GPIO0 for PWM channel 3 (only used in the RGB test)
const int TONEpin = 12; // D6, GPIO12 for a tone output
const int SERVO1pin = 13; // D7, GPIO13 for the first servo
const int SERVO2pin = 15; // D8, GPIO15 for the second servo
const int TP1 = 16; // D0, GPIO16 test point, toggles with each PWM inc/dec loop
const int TP2 = 14; // D5, GPIO14 test point, toggles with each PWM change
const int TP3 = 4; // D2, GPIO4 test point, toggles around timer1Interrupt ISR
uint32_t freqPWM = 977; // initial PWM frequency, max 977Hz if you want all 1023 steps
uint32_t dutyCycle = 1; // starting duty cycle of the PWM output(s)
uint32_t minDutyCycle = 0; // minimum duty cycle, 0-1023 (at 0 pin is low / PWM disconnected)
uint32_t maxDutyCycle = 1023; // maximum duty cycle 0-1023 (at 1023 pin is high / PWM disconnected)
uint32_t pauseDutyCycle = 10E3; // pause between duty cycle changes
int incPWM = 1; // increment/decrement the PWM sweep loop
uint32_t loopDelay = 0; // delay between INC/DEC loops
bool firstChannel = true; // one channel PWM output
bool secondChannel = true; // one or two channel PWM output
bool thirdChannel = true; // one, two or three channel PWM output
bool valueOutput = false; // print the PWM duty cycle values to the terminal
bool voltageOutput = false; // print the ADC value to the terminal
bool hold = true; // if true stops the INC/DEC cycling
bool rgbTest = false; // if true output dutyCycle on all 3 channels, changing values simultaneously
bool keepCH1 = false; // if true, freeze CH1 PWM during RGB test, +/-/d still effect it
bool eightChTest = false; // if true, output 20KHz PWM on 8 GPIOs (disconnect servos!)
uint32_t dutyCH1 = 0; // CH1 duty cycle for fixed RGB test
uint32_t toneFreq = 0; // default no tone output
uint32_t expiry = 0; // expiry for tone & servo commands
bool sirenTone = 0; // toggle for the siren tone output
bool sirenFreq = 0; // high/low frequency
int32_t servo1Angle = 90; // SERVO1 set to neutral but not enabled
int32_t servo2Angle = 90; // SERVO2 set to neutral but not enabled
int servoIncr = 5; // inc/dec for the servo sweep funtion
int servoStep = servoIncr;
bool waveServos = false; // if true, start sweeping the servos back and forth
uint16_t servoHigh = 0; // default alt method of driving servo1 off
uint16_t servoLow = 18; // milliseconds after the servo pulse
uint32_t ledPWM = 1025; // LED_BUILTIN PWM [0-1023] @ 1KHz
bool wifiDisabled = true; // WiFi initially disabled
bool otaEnabled = true; // OTA enabled/disabled
String command; // stores the requested command from the serial terminal
esp8266::polledTimeout::periodicFastUs pwmTimeout(pauseDutyCycle); // initially 10ms between PWM duty cycle changes
esp8266::polledTimeout::periodicMs servoTimeout(60); // fixed 60ms between servo sweep changes so it can settle
esp8266::polledTimeout::periodicMs sirenTimeout(650); // fixed 650ms between siren tone changes
Servo servo1;
Servo servo2;
void setup() {
Serial.begin(74880); // start serial for terminal
Serial.println();
Serial.println(ESP.getFullVersion());
Serial.println(F("\nPWM / Tone / Servo test program (press ? and <enter> for help)\n"));
pinMode(TP1, OUTPUT); // test point for outer loop
pinMode(TP2, OUTPUT); // test point for duty cycle changes
pinMode(TP3, OUTPUT); // test point for ISR
GPOC = (1 << 4); // TP3 / D2 used for checking timer1Interrupt() latency
pinMode(SERVO1pin, OUTPUT); // avoids high-impedance noise pickup
pinMode(SERVO2pin, OUTPUT); // avoids high-impedance noise pickup
analogWriteRange(1023); // due to new default AVR compatibility, https://github.com/esp8266/Arduino/pull/7456
if (!wifiDisabled) {
initWiFi();
if (otaEnabled)
initOTA();
} else {
Serial.println(F("WiFi disabled, enter Y to enable it"));
disableWiFi();
}
}
void loop() {
if (pwmTimeout && !hold)
sweepPWM();
if (servoTimeout && waveServos)
sweepServos();
if (sirenTimeout && sirenTone)
toggleSiren();
commandCheck();
if (WiFi.localIP() && (WiFi.status() == WL_CONNECTED) && otaEnabled)
ArduinoOTA.handle(); //see if we need to reflash
yield();
}
void sweepPWM() {
digitalWrite(TP2, !digitalRead(TP2)); // toggle around duty cycle changes disabled for quick test
if (dutyCycle <= minDutyCycle) { // increase duty cycle, decrease for second channel
incPWM = 1;
digitalWrite(TP1, HIGH); // toggle the loop activity LED
if (valueOutput)
Serial.println(F("loop switch-over"));
delay(loopDelay); // completed one half sweep loop
}
if (dutyCycle >= maxDutyCycle) {
incPWM = -1;
digitalWrite(TP1, LOW); // toggle the loop activity LED
if (valueOutput)
Serial.println(F("loop switch-over"));
delay(loopDelay); // completed one half sweep loop
}
if (!rgbTest) { // sweep one or two channels in opposition from min to max and back
if (firstChannel)
analogWrite(CH1pin, dutyCycle);
if (secondChannel)
analogWrite(CH2pin, 1023 - dutyCycle);
if (valueOutput) {
Serial.print(F("CH1 = "));
if (firstChannel) {
Serial.print(dutyCycle);
} else {
Serial.print(F("disabled"));
}
Serial.print(F(" CH2 = "));
if (secondChannel) {
Serial.print(1023 - dutyCycle);
} else {
Serial.print(F("disabled"));
}
Serial.println();
if (voltageOutput) { // this prints the PREVIOUS value, would need a delay to get current value
float volts = 3.3 * analogRead(A0) / 1024;
Serial.print(F("voltage = "));
Serial.println(volts);
}
}
} else { // RGB test, sweep all 3 channels up and down together
if (valueOutput && (firstChannel || secondChannel || thirdChannel)) {
Serial.print(F("RGB channels at "));
Serial.println(dutyCycle);
}
if (firstChannel && !keepCH1)
analogWrite(CH1pin, dutyCycle); // inverted for common-anode LEDs (1023 = bright with MOSFET drivers)
if (secondChannel)
analogWrite(CH2pin, dutyCycle);
if (thirdChannel)
analogWrite(CH3pin, dutyCycle);
}
dutyCycle += incPWM;
}
void sweepServos() {
servo1Angle += servoStep;
if (servo1Angle >= 180) {
servoStep = -(servoIncr);
servo1Angle = 180;
}
if (servo1Angle <= 0) {
servoStep = servoIncr;
servo1Angle = 0;
}
servo1.write(servo1Angle);
servo2Angle = 180 - servo1Angle;
servo2.write(servo2Angle);
}
void toggleSiren() {
sirenFreq = !sirenFreq;
tone(TONEpin, sirenFreq ? 440 : 585);
}
void commandCheck() {
if (Serial.available()) { // serial command processor
command = Serial.readStringUntil('\n');
command.trim(); // strip the newline
if (command.equalsIgnoreCase("help") || command.equals("?")) // terminal commands list
{
Serial.println(F("\nAvailable commands: (all commands terminated by <enter>)"));
Serial.println(F("2000f sets PWM frequency to 2000Hz, doesn't update until the duty cycle changes"));
Serial.println(F("r toggles RGB test mode, sweeping all 3 PWM outputs }else{ alternate CH1 & CH2"));
Serial.println(F("k toggles freezing CH1 PWM in RGB test, +/-/d still effect CH1"));
Serial.println(F("h toggles holding current duty cycle or continues the PWM/RGB sweep"));
Serial.println(F("+ increments the duty cycle while in HOLD, ignoring min/max"));
Serial.println(F("- decrements the duty cycle while in HOLD, ignoring min/max"));
Serial.println(F("300d set the duty cycle of CH1 to 300 while in HOLD"));
Serial.println(F("u toggles the first PWM channel on/off"));
Serial.println(F("c toggles the second PWM channel on/off"));
Serial.println(F("g toggles the third PWM channel on/off"));
Serial.println(F("10000p sets the pause between duty cycle changes to 10ms"));
Serial.println(F("30m sets PWM minimum duty cycle to 30/1023"));
Serial.println(F("900x sets PWM maximum duty cycle to 900/1023"));
Serial.println(F("1020j sets the LED_BUILTIN to 1020 (dim) with analogWrite, 'j' disables LED_BUILTIN"));
Serial.println(F("1020L sets the LED_BUILTIN to 1020 (dim) with startWaveform(high,low,0)"));
Serial.println(F("& toggles 8 channel 20KHz analogWrite() PWM test"));
Serial.println(F("o toggles printing the PWM values"));
Serial.println(F("v toggles printing the ADC input reading (in volts)"));
Serial.println(F("500t plays a 500Hz tone, 0t or t stops the tone, range 1Hz-20KHz"));
Serial.println(F("500e plays the tone for 500ms, 0e or e sets no expiry/infinite duration"));
Serial.println(F("q toggles the siren tone on/off"));
Serial.println(F("90s sets the 1st servo to 90 degrees, > 180 or 's' detaches the servo"));
Serial.println(F("90a sets the 2nd servo to 90 degrees, > 180 or 'a' detaches the servo"));
Serial.println(F("w toggles sweeping the servos from 0 to 180 and back"));
Serial.println(F("1500b sets the 1st servo to 90 degrees, 'b' detaches the servo"));
Serial.println(F("20n sets a 20ms pause after the servo1 pulse, default 18"));
Serial.println(F("y toggles WiFi & OTA on/off"));
Serial.println(F("z does an ESP.restart()"));
Serial.println(F("i displays the current settings\n"));
} else {
switch ( command.charAt(command.length() - 1) ) { // get the last byte (the requested command)
case 'u': case 'U': // U toggles the first PWM channel on/off
firstChannel = !firstChannel;
Serial.print(F("running PWM channels "));
if (firstChannel)
Serial.print(F("1 "));
if (secondChannel)
Serial.print(F("2 "));
if (thirdChannel)
Serial.print(F("3"));
if (!firstChannel) {
analogWrite(CH1pin, 0);
stopWaveform(CH1pin);
}
if (!firstChannel && !secondChannel && !thirdChannel)
Serial.print(F("<none>"));
Serial.println();
break;
case 'c': case 'C': // C toggles the second PWM channel on/off
secondChannel = !secondChannel;
Serial.print(F("running PWM channels "));
if (firstChannel)
Serial.print(F("1 "));
if (secondChannel)
Serial.print(F("2 "));
if (thirdChannel)
Serial.print(F("3"));
if (!secondChannel) {
analogWrite(CH2pin, 0);
stopWaveform(CH2pin);
}
if (!firstChannel && !secondChannel && !thirdChannel)
Serial.print(F("<none>"));
Serial.println();
break;
case 'g': case 'G': // G toggles the third PWM channel on/off
thirdChannel = !thirdChannel;
Serial.print(F("running PWM channels "));
if (firstChannel)
Serial.print(F("1 "));
if (secondChannel)
Serial.print(F("2 "));
if (thirdChannel)
Serial.print(F("3"));
if (!thirdChannel) {
analogWrite(CH3pin, 0);
stopWaveform(CH3pin);
}
if (!firstChannel && !secondChannel && !thirdChannel)
Serial.print(F("<none>"));
Serial.println();
break;
case 'h': case 'H': // H freezes at current duty cycle, or free-runs the sweep loops
hold = !hold;
if (hold) {
Serial.print(F("holding PWM at current CH1 duty cycle = "));
Serial.println(dutyCycle);
if (voltageOutput) { // this prints the current value after a delay
delay(150);
float volts = 3.3 * analogRead(A0) / 1024;
Serial.print(F("voltage = "));
Serial.println(volts);
}
} else {
analogWriteFreq(freqPWM); // start the PWM (must change duty cycle for PWM freq to update)
Serial.print(F("incrementing / decrementing PWM duty cycle at PWM freq = "));
Serial.print(freqPWM);
Serial.println(F("Hz"));
}
break;
case '+': // + increment the duty cycle in HOLD, min / max ignored
if (dutyCycle < 1023)
dutyCycle++;
if (dutyCH1 < 1023)
dutyCH1++;
if (firstChannel) {
if (rgbTest && keepCH1)
analogWrite(CH1pin, dutyCH1);
else
analogWrite(CH1pin, dutyCycle);
Serial.print(F("dec duty cycle of CH1 to "));
Serial.print(dutyCH1);
}
if (secondChannel && !rgbTest) {
analogWrite(CH2pin, 1023 - dutyCycle);
Serial.print(F(" duty cycle of CH2 set to "));
Serial.print(1023 - dutyCycle);
}
if (rgbTest) {
if (secondChannel)
analogWrite(CH2pin, dutyCycle);
if (thirdChannel)
analogWrite(CH3pin, dutyCycle);
Serial.print(F(" duty cycle of CH2 & CH3 set to "));
Serial.print(dutyCycle);
}
Serial.println();
if (voltageOutput) { // this prints the current value after a delay
delay(150);
float volts = 3.3 * analogRead(A0) / 1024;
Serial.print(F("ADC input voltage = "));
Serial.println(volts);
}
break;
case '-': // - decrement the duty cycle, min / max ignored
if (dutyCycle > 0)
dutyCycle--;
if (dutyCH1 > 0)
dutyCH1--;
if (firstChannel) {
if (rgbTest && keepCH1)
analogWrite(CH1pin, dutyCH1);
else
analogWrite(CH1pin, dutyCycle);
Serial.print(F("dec duty cycle of CH1 to "));
Serial.print(dutyCH1);
}
if (secondChannel && !rgbTest) {
analogWrite(CH2pin, 1023 - dutyCycle);
Serial.print(F(" duty cycle of CH2 set to "));
Serial.print(1023 - dutyCycle);
}
if (rgbTest) {
if (secondChannel)
analogWrite(CH2pin, dutyCycle);
if (thirdChannel)
analogWrite(CH3pin, dutyCycle);
Serial.print(F(" duty cycle of CH2 & CH3 set to "));
Serial.print(dutyCycle);
}
Serial.println();
if (voltageOutput) { // this prints the current value after a delay
delay(150);
float volts = 3.3 * analogRead(A0) / 1024;
Serial.print(F("ADC input voltage = "));
Serial.println(volts);
}
break;
case 'd': case 'D': // 300d sets the duty cycle for CH1 to 300 in HOLD, min / max ignored
command.remove(command.length() - 1);
dutyCycle = (uint32_t) (command.toInt());
if (dutyCycle > 1023)
dutyCycle = 1023;
dutyCH1 = dutyCycle;
Serial.print(F("duty cycle of CH1 set to "));
Serial.print(dutyCH1);
if (secondChannel && !rgbTest) {
analogWrite(CH2pin, 1023 - dutyCycle);
Serial.print(F(" duty cycle of CH2 set to "));
Serial.println(1023 - dutyCycle);
}
if ((secondChannel || thirdChannel) && rgbTest) {
if (secondChannel)
analogWrite(CH2pin, dutyCycle);
if (thirdChannel)
analogWrite(CH3pin, dutyCycle);
Serial.print(F(" duty cycle of CH2 and/or CH3 set to "));
Serial.print(dutyCycle);
}
if (firstChannel)
analogWrite(CH1pin, dutyCycle);
if (voltageOutput) { // this prints the current value after a delay
delay(150);
float volts = 3.3 * analogRead(A0) / 1024;
Serial.print(F("voltage = "));
Serial.println(volts);
}
Serial.println();
break;
case 'f': case 'F': // 100f sets the PWM frequency to 100Hz, default ~1KHz
command.remove(command.length() - 1);
freqPWM = (uint32_t) (command.toInt());
analogWriteFreq(freqPWM);
Serial.print(F("PWM frequency "));
Serial.print(freqPWM);
Serial.println("Hz");
break;
case 'p': case 'P': // 10000p sets the pause between duty cycle changes to 10ms
command.remove(command.length() - 1);
pauseDutyCycle = (uint32_t) (command.toInt());
pwmTimeout.reset(pauseDutyCycle);
Serial.print(F("delay between duty cycle changes "));
Serial.print(pauseDutyCycle);
Serial.println(" us");
break;
case 'o': case 'O': // o toggles printing duty cycle values to serial terminal
valueOutput = !valueOutput;
break;
case 'v': case 'V': // v toggles printing the read ADC values to serial terminal
voltageOutput = !voltageOutput;
if (voltageOutput) {
Serial.println(F("analog read displayed"));
delay(150);
float volts = 3.3 * analogRead(A0) / 1024;
Serial.print(F("voltage = "));
Serial.println(volts);
} else {
Serial.println(F("analog read disabled"));
}
break;
case 'm': case 'M': // 10m sets the minimum PWM duty cycle to 10/1022
command.remove(command.length() - 1);
minDutyCycle = (unsigned int) (command.toInt());
Serial.print(F("minimum duty cycle "));
Serial.println(minDutyCycle);
break;
case 'x': case 'X': // 900x sets the maximum PWM duty cycle to 900/1022
command.remove(command.length() - 1);
maxDutyCycle = (unsigned int) (command.toInt());
Serial.print(F("maximum duty cycle "));
Serial.println(maxDutyCycle);
break;
case 't': case 'T': // 500t plays a 500Hz tone, 0t or t stops the tone
command.remove(command.length() - 1);
toneFreq = (unsigned int) (command.toInt());
if (toneFreq == 0) {
noTone(TONEpin);
Serial.println(F("tone stopped"));
} else {
tone(TONEpin, toneFreq, expiry);
Serial.print(toneFreq);
Serial.println(F("Hz tone output"));
}
break;
case 'e': case 'E': // expiry in ms for tone & servo commands
command.remove(command.length() - 1);
expiry = (unsigned int) (command.toInt());
if ((expiry == 0) || (command.length() == 0)) {
expiry = 0;
Serial.println(F("expiry disabled"));
} else {
Serial.print(F("expiry for tone & servo = "));
Serial.print(expiry);
Serial.println(F(" ms"));
}
break;
case 'q': case 'Q': // q toggles the siren tone on/off
sirenTone = !sirenTone;
if (!sirenTone) {
noTone(TONEpin);
Serial.println(F("siren tone stopped"));
} else {
// tone(TONEpin, sirenFreq ? 440 * 4 : 440 / 2); // alternating 1760/220Hz tone
tone(TONEpin, sirenFreq ? 440 : 585); // alternating polizei tone
Serial.println(F("siren tone output"));
}
break;
case 's': case 'S': // 90s puts the first servo at 90 degrees (neutral)
command.remove(command.length() - 1);
servo1Angle = (unsigned int) (command.toInt());
if ((servo1Angle > 180) || (command.length() == 0)) {
servo1.detach();
Serial.println(F("servo1 detached"));
} else {
servo1.attach(SERVO1pin);
servo1.write(servo1Angle);
Serial.print(F("servo1 angle ~ "));
Serial.print(servo1Angle);
Serial.println(F(" degrees"));
}
break;
case 'a': case 'A': // 90a puts the second servo at 90 degrees (neutral)
command.remove(command.length() - 1);
servo2Angle = (unsigned int) (command.toInt());
if ((servo2Angle > 180) || (command.length() == 0)) {
servo2.detach();
Serial.println(F("servo2 detached"));
} else {
servo2.attach(SERVO2pin);
servo2.write(servo2Angle);
Serial.print(F("servo2 angle ~ "));
Serial.print(servo2Angle);
Serial.println(F(" degrees"));
}
break;
case 'w': case 'W': // w toggles sweeping the servos from 0 to 180 and back
waveServos = !waveServos;
if (waveServos) {
Serial.println(F("sweeping servos"));
servo1.attach(SERVO1pin);
servo2.attach(SERVO2pin);
servo1.write(servo1Angle);
servo2Angle = 180 - servo1Angle;
servo2.write(servo2Angle);
delay(300); // give it a chance to slew to the initial position
} else {
Serial.print(F("stopping the servo sweep at "));
Serial.print(servo1Angle);
Serial.println(F(" degrees (Servo1)"));
servo1.detach();
servo2.detach();
}
break;
case 'b': case 'B': // 1500b sets the 1st servo to 90 degrees, 'b' detaches the servo
command.remove(command.length() - 1);
servoHigh = (unsigned int) (command.toInt());
if (command.length() == 0) {
stopWaveform(SERVO1pin);
Serial.println(F("servo1 detached"));
} else {
startWaveform(SERVO1pin, servoHigh, servoLow * 1000, 0);
Serial.print(F("servo1 pulse "));
Serial.print(servoHigh);
Serial.println(F(" us"));
}
break;
case 'n': case 'N': // 20n sets a 20ms pause after the servo1 pulse, default 18
command.remove(command.length() - 1);
servoLow = (unsigned int) (command.toInt());
if (command.length() == 0) {
stopWaveform(SERVO1pin);
Serial.println(F("servo1 detached"));
} else {
startWaveform(SERVO1pin, servoHigh, servoLow * 1000, 0);
Serial.print(F("servo1 pause "));
Serial.print(servoLow);
Serial.println(F(" ms"));
}
break;
case 'r': case 'R': // r toggles RGB test mode, sweeping all 3 PWM outputs simultaneously
rgbTest = !rgbTest;
if (rgbTest) {
Serial.println(F("sweeping all 3 PWM channels"));
hold = false;
} else {
Serial.println(F("stopping the RGB channel sweep"));
thirdChannel = false;
stopWaveform(CH3pin);
hold = true;
}
break;
case 'k': case 'K': // k toggles freezing CH1 PWM in RGB test, +/-/d still effect CH1
keepCH1 = !keepCH1;
if (keepCH1) {
dutyCH1 = dutyCycle;
Serial.print(F("freezing CH1 PWM at "));
Serial.println(dutyCH1);
} else {
Serial.println(F("sweeping CH1 with the other channels"));
}
break;
case 'j': case 'J': // 1020j sets the LED_BUILTIN to 1020 (dim), 'j' disables LED_BUILTIN
command.remove(command.length() - 1);
ledPWM = (unsigned int) (command.toInt());
if ((ledPWM > 1023) || (command.length() == 0)) {
stopWaveform(LED_BUILTIN);
Serial.println(F("LED_BUILTIN detached"));
ledPWM = 1025;
} else {
// uint32_t ledHIGH = 1000 * ledPWM / 1023;
// uint32_t ledLOW = 1000 - ledHIGH;
// startWaveform(LED_BUILTIN, ledHIGH, ledLOW, 0);
analogWrite(LED_BUILTIN, ledPWM);
Serial.print(F("LED_BUILTIN PWM set to "));
Serial.println(ledPWM);
}
break;
case 'l': case 'L': // 1020L sets the LED_BUILTIN to 1020 (dim) with startWaveform(high,low,0)
command.remove(command.length() - 1);
ledPWM = (unsigned int) (command.toInt());
if ((ledPWM > 1023) || (command.length() == 0)) {
stopWaveform(LED_BUILTIN);;
Serial.println(F("LED_BUILTIN detached"));
ledPWM = 1025;
} else {
uint32_t ledHIGH = 1000 * ledPWM / 1023;
uint32_t ledLOW = 1000 - ledHIGH;
startWaveform(LED_BUILTIN, ledHIGH, ledLOW, 0);
Serial.print(F("LED_BUILTIN PWM set to "));
Serial.println(ledPWM);
}
break;
case '&': // & toggles 8 channel PWM test on/off
eightChTest = !eightChTest;
if (!eightChTest) {
Serial.println(F("stopping 8CH PWM test"));
analogWrite(0, 0);
analogWrite(2, 0);
analogWrite(4, 0);
analogWrite(5, 0);
analogWrite(12, 0);
analogWrite(13, 0);
analogWrite(14, 0);
analogWrite(15, 0);
} else {
Serial.println(F("starting 8CH PWM test"));
analogWrite(0, 500);
analogWrite(2, 500);
analogWrite(4, 500);
analogWrite(5, 500);
analogWrite(12, 500);
analogWrite(13, 500);
analogWrite(14, 500);
analogWrite(15, 500);
}
break;
case 'y': case 'Y': // y toggles WiFi on/off
wifiDisabled = !wifiDisabled;
if (!wifiDisabled) {
initWiFi();
if (otaEnabled)
initOTA();
} else {
Serial.println(F("disabling WiFi"));
disableWiFi();
}
break;
case 'z': case 'Z': // z does an ESP.restart()
Serial.println(F("restarting..."));
delay(500);
ESP.restart();
break;
case 'i': case 'I': // i displays the current settings
{
Serial.println(F("\nCurrent settings:"));
Serial.print(F("PWM frequency = "));
Serial.print(freqPWM);
Serial.println(" Hz");
Serial.print(F("PWM alternate sweep = "));
if (hold && !rgbTest)
Serial.println(F("hold"));
if (!hold && !rgbTest)
Serial.println(F("running"));
if (rgbTest)
Serial.println(F("off"));
Serial.print(F("RGB sweep = "));
if (!rgbTest)
Serial.println(F("off"));
if (rgbTest && keepCH1 && !hold) {
Serial.print(F("running, CH1 fixed at "));
Serial.println(dutyCH1);
}
if (rgbTest && !keepCH1 && !hold)
Serial.println(F("running"));
if (rgbTest && hold)
Serial.println(F("hold"));
Serial.print(F("minimum duty cycle = "));
Serial.println(minDutyCycle);
Serial.print(F("maximum duty cycle = "));
Serial.println(maxDutyCycle);
Serial.print(F("PWM CH1 = "));
if (!firstChannel) {
Serial.print(F("disabled"));
} else {
if (rgbTest && keepCH1)
Serial.print(dutyCH1);
else
Serial.print(dutyCycle);
}
Serial.print(F(" PWM CH2 = "));
if (!secondChannel)
Serial.print(F("disabled"));
if (secondChannel && !rgbTest)
Serial.print(1023 - dutyCycle);
if (secondChannel && rgbTest)
Serial.print(dutyCycle);
Serial.print(F(" PWM CH3 = "));
if (!rgbTest)
Serial.println(F("disabled"));
else
Serial.println(dutyCycle);
Serial.print(F("8 CH PWM test "));
if (eightChTest)
Serial.println(F("running"));
else
Serial.println(F("stopped"));
float volts = 3.3 * analogRead(A0) / 1024;
Serial.print(F("ADC input voltage = "));
Serial.println(volts);
Serial.print(F("pause between PWM changes = "));
Serial.print(pauseDutyCycle);
Serial.println(F(" us"));
Serial.print(F("Tone output = "));
if (toneFreq == 0 && !sirenTone)
Serial.println(F("disabled"));
else {
if (sirenTone)
Serial.println(F("siren tone output"));
else {
Serial.print(toneFreq);
Serial.print(F(" Hz duration = "));
Serial.print(expiry);
Serial.println(F(" ms"));
}
}
Serial.print(F("Servo1 = "));
if (servo1.attached())
Serial.print(servo1Angle);
else
Serial.print(F("detached"));
Serial.print(F(" Servo2 = "));
if (servo2.attached())
Serial.print(servo2Angle);
else
Serial.print(F("detached"));
Serial.print(F(" servo sweep = "));
if (waveServos)
Serial.println(F("on"));
else
Serial.println(F("off"));
Serial.print(F("LED_BUILTIN PWM = "));
if (ledPWM < 1025) {
Serial.println(ledPWM);
// Serial.print(F(" @ "));
// Serial.print(freqPWM);
// Serial.println(F(" Hz"));
}
else
Serial.println(F("disabled"));
Serial.print(F("WiFi "));
if (WiFi.localIP()) {
Serial.print(F("connected at "));
Serial.println(WiFi.localIP());
}
else
Serial.println(F("disabled\n"));
break;
}
default:
break;
}
}
}
}
void disableWiFi() {
WiFi.forceSleepBegin(); // sleep the modem to reduce noise & WiFi interrupts during measurements
delay(10); // it doesn't always go to sleep unless you delay(10)
}
void initWiFi() {
/* Explicitly set the ESP8266 to be a WiFi-client, otherwise by default it
would try to act as both a client and an access-point and could cause
network-issues with other WiFi devices on your network. */
GPOS = (1 << 4); // TP3 / D2 used for checking timer1Interrupt() latency
Serial.println(F("enabling WiFi"));
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.setOutputPower(5); // in dBm, set this higher or lower if you have connection issues
WiFi.config(staticIP, gateway, subnet); // if using static IP, enter parameters at the top
WiFi.begin(ssid, password);
delay(1);
Serial.print(F("Connecting to "));
Serial.println(ssid);
Serial.print(F("my MAC: "));
Serial.println(WiFi.macAddress());
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.print(F("."));
delay(500);
}
Serial.print(F("IP address: "));
Serial.println(WiFi.localIP());
Serial.println(F("WiFi ready"));
if (MDNS.begin("esp8266")) {
Serial.println(F("MDNS responder started"));
}
if (!otaEnabled)
Serial.println(F("OTA disabled"));
GPOC = (1 << 4); // TP3 / D2 used for checking timer1Interrupt() latency
}
void initOTA() {
// Port defaults to 8266
// ArduinoOTA.setPort(8266);
// Hostname defaults to esp8266-[ChipID]
// ArduinoOTA.setHostname("myesp8266");
// No authentication by default
// ArduinoOTA.setPassword((const char *)"123");
ArduinoOTA.onStart([]() {
Serial.println(F("OTA Start"));
});
ArduinoOTA.onEnd([]() {
Serial.println(F("\nOTA Complete"));
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\n", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println(F("Auth Failed"));
else if (error == OTA_BEGIN_ERROR) Serial.println(F("Begin Failed"));
else if (error == OTA_CONNECT_ERROR) Serial.println(F("Connect Failed"));
else if (error == OTA_RECEIVE_ERROR) Serial.println(F("Receive Failed"));
else if (error == OTA_END_ERROR) Serial.println(F("End Failed"));
});
ArduinoOTA.begin();
yield();
Serial.println(F("OTA enabled"));
}
@Tech-TX

Tech-TX commented Apr 22, 2020

Copy link
Copy Markdown
Author

synth

@Tech-TX

Tech-TX commented Nov 7, 2020

Copy link
Copy Markdown
Author

pwm test jig schematic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment