Skip to content

Instantly share code, notes, and snippets.

@Tech-TX
Last active November 21, 2020 19:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tech-TX/572aab942d44638566e07036fe77a4c6 to your computer and use it in GitHub Desktop.
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
Copy link
Author

Tech-TX commented Apr 22, 2020

synth

@Tech-TX
Copy link
Author

Tech-TX commented Nov 7, 2020

pwm test jig schematic

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