/*-----------------------------------------------------------------------------------------
* This software is in the public domain, furnished "as is", without technical
* support, and with no warranty, express or implied, as to its usefulness for
* any purpose.
*
* Strawap38MVF_ESP.ino:
*
* ESP32-WROOM-32 microcontroller software project to implement functionality for a
* two wheel driven RC amphi-tank (Strawap38MFV).
* This is the main control loop to trigger the below listed functions.
*
* - RCPWMRead.ino: reading PWM signals from RC receiver and signal quality checks.
* The functions based on the RC engine sound & LED controller for Arduino ESP32
* written by TheDIYGuy999 and migrated functionality from pwmread_rcfailsafe.ino
* written by Kelvin Nelson.
*
* - DualDriveMix3CH.ino: control of 2 motorshilds (BTS7960) to drive and steer the
* amphi-tank with two different modes
*
* - Multiswitch.ino: 4 times multiswitch decoder to trigger different functions of
* the tank. Hardware design of encoder was taken from www.rc-bastelbu.de YaMS
* implementation of Dirk Wiedemann
*
* - LED.ino: control of a RGB-LED to show the different driving states, failsave
* or wateralert
*
* - Sound.ino: sound controller for engine, sirene, gun and wateralert based on the
* RC engine sound & LED controller for Arduino ESP32 written by TheDIYGuy999
*
* - Watersensor.ino: reading of digital humidity sensor as wateralert implementation
*
* Author: Volker Frauenstein
* Date: 03/03/2021 Version 2.1: functions x_RCpwmRange for easy RC signal calibration
* and RC interrupt performance optimisation added
* Global definitions outsourced to new Strawap38MVF_ESP.h
*
* Date: 29/01/2021 Version 2.0: documentation completed and blinking function to RGB-LED added
* Date: 08/01/2021 Version 1.3: RGB-LED function adapted
* Date: 06/01/2021 Version 1.2: migration of sound functions added
* Date: 05/01/2021 Version 1.1: RGB-LED, Multiswitch and wateralert function added
* Date: 02/01/2021 Version 1.0: migration of RC signal readings to ESP32 microcontroller
*/
// SW version definition
String Strawap = "StrawapMFV38 - SW Version 2.1 (for ESP32 WROOM DEV)";
// include for function and datstructur definitions
#include "Strawap38MVF_ESP.h"
// generig definitions
//#define DEBUG_M 1 // set activ if debuging for main loop is needed
#ifdef DEBUG_M
unsigned long lastloop = 0;
#endif
// =======================================================================================================
// SETUP FUNCTIONS
// =======================================================================================================
void setup() {
// Serial setup
Serial.begin(115200); // USB serial (for DEBUG)
Serial.print(" Start up of ");Serial.println(Strawap);
setupRCpwm(); // setup read of RC PWM signals of defined channels
close_DualDrive(); // disable motorshilds and motors for start up
setup_MultiSwitch(); // define multiswitch Pinout
close_MultiSwitch(); // and close states at startup
setup_LEDstate(); // setup RGB-LED
sound_setup(); // setup for sound
setup_watersensor(); // setup for water alarm
}
// =======================================================================================================
// MAIN LOOP, RUNNING ON CORE 1
// =======================================================================================================
void loop() {
if (pwmRCcycle > PWM_CHANNELS_NUM) { // new pwm signals measured on all GIO Pins
#ifdef DEBUG_M
unsigned long looptime = millis();
Serial.print("RC pwm duration: ");Serial.print(looptime - lastloop);Serial.print("ms");
lastloop = looptime;
#endif
readPwmSignals(); // collect and normalise RC pwm input
pwmRCcycle = 1; // prepare for next RC signal cycle (every 20 ms)
pwm_cycle = true; // trigger RC loop on Core 0
// old RC systems can have scattering on pwm signal, therefor the out of bound check will not do the job
failed_now = RCpwmScattering(); // check RC signal scattering
if ( failed_before > 0 ) { // failsafe for scattering reasons is activ
if ( !failed_now ) { // check if signal quality is now good againg
if ( count_good > 10 ) {
start_DualDriveMix(); // signal was 10 times good, enable motors againg
failed_before = false; // and clean up for next check
count_good = 0;
set_LEDstate(6); // LED off
#ifdef DEBUG_M
Serial.print(" Start ");
#endif
}
else {
count_good = count_good + 1; // signal is good -> count good time
set_LEDstate(0); // LED set to red
#ifdef DEBUG_M
Serial.print(" Wait ");
#endif
}
}
else { // signal is still or againg bad
count_good = 0; // reset good time counter
#ifdef DEBUG_M
Serial.print(" Reset ");
#endif
}
}
else { // RC signal was good
if ( !failed_now ) { // check if it is still good
run_DualDrive(0, 1, 2); // Mix the drives with RC channels 1, 2 and 4 (RC_in[0],RC_in[1],RC_in[2])
run_MultiSwitch(3); // check state of Multiswitch on channel 6 (RC_in[3] and handle pinout
// triggering switchable sounds
engineOnOff(switchOn[0]); // Switch engine on or off
triggerSiren(switchOn[1]); // sound for combat siren depending on switch b
triggerSound1(switchOn[2]); // sound for MG fire depending on switch c
count_good = 0;
#ifdef DEBUG_M
Serial.print(" Run ");
#endif
}
else { // RC signal has gone bad now, do failsafe and disable motors and Multiswitch
close_DualDrive(); // disable motors
close_MultiSwitch(); // and Multiswitch
failed_before = true; // prepare for next check
set_LEDstate(0); // LED set to red
// shutoff sounds
engineOnOff(false); // Switch engine on or off
triggerSiren(false); // sound for combat siren depending on switch b
triggerSound1(false); // sound for MG fire depending on switch c
count_good = 0;
#ifdef DEBUG_M
Serial.print(" Stop ");
#endif
}
} // end failsafe check for old RCs
mapThrottle(power); // Map pulsewidth to throttle
triggerHorn(checkwater()); // check for wateralarm and trigger horn if needed
#ifdef DEBUG_M // show debug data if needed
looptime = millis() - looptime;
Serial.print(", Mainloop runtime: ");Serial.print(looptime);Serial.println("ms");
#endif
} // end loop on RC signal detection
} // end Loop
// =======================================================================================================
// 1st MAIN TASK, RUNNING ON CORE 0 (Interrupts are running on this core as well)
// =======================================================================================================
void Task1code(void *pvParameters) {
for (;;) {
dacOffsetFade(); // DAC offset fader for sounds
if (pwm_cycle) { // RC Signal needed for update of functions
pwm_cycle = false; // prepare for next RC signal cycle (every 20 ms)
engineMassSimulation(); // Simulate engine mass, generate RPM signal
automaticGearSelector(); // call gear selector
DriveState(); // set Drivestate for engine sound simulation
}
}
}