first draft
This commit is contained in:
commit
1ecf83fcc7
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
20
fuses.py
Normal file
20
fuses.py
Normal file
@ -0,0 +1,20 @@
|
||||
from os.path import join
|
||||
Import("env")
|
||||
|
||||
conf_path = join(env.PioPlatform().get_package_dir("tool-avrdude"), "avrdude.conf")
|
||||
|
||||
env.Replace(
|
||||
FUSEUPLOADER="avrdude",
|
||||
FUSEFLAGS=[
|
||||
"-C", conf_path,
|
||||
"-p", "atmega328p",
|
||||
"-Pusb",
|
||||
"-c", "jtag3isp"
|
||||
],
|
||||
FUSECOMMAND="$FUSEUPLOADER $FUSEFLAGS -U lfuse:w:0xE6:m -U hfuse:w:0xDA:m -U efuse:w:0x05:m"
|
||||
)
|
||||
|
||||
def set_fuses(source, target, env):
|
||||
env.Execute(env.VerboseAction("$FUSECOMMAND", "Setting Fuses..."))
|
||||
|
||||
env.AddPreAction("upload", set_fuses)
|
39
include/README
Normal file
39
include/README
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
lib/README
Normal file
46
lib/README
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
30
platformio.ini
Normal file
30
platformio.ini
Normal file
@ -0,0 +1,30 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:nanoatmega328new]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328new
|
||||
framework = arduino
|
||||
|
||||
;upload_protocol = custom
|
||||
;upload_flags =
|
||||
; -C
|
||||
; ${platformio.packages_dir}/tool-avrdude/avrdude.conf
|
||||
; -p
|
||||
; atmega328p
|
||||
; -Pusb
|
||||
; -c
|
||||
; jtag3isp
|
||||
;upload_command = avrdude $UPLOAD_FLAGS -U flash:w:$SOURCE:i
|
||||
|
||||
;extra_scripts = fuses.py
|
||||
|
||||
lib_deps =
|
||||
adafruit/Adafruit SSD1306 @ ^2.5.13
|
59
src/MotorController.cpp
Normal file
59
src/MotorController.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// MotorController.cpp
|
||||
#include "MotorController.h"
|
||||
|
||||
const MotorConfig defaultConfig = {
|
||||
.minPWM = 0,
|
||||
.maxPWM = 255,
|
||||
.inverted = false,
|
||||
.responseSpeed = 10,
|
||||
.lookupTable = {0, 28, 57, 85, 114, 142, 171, 199, 228, 255}
|
||||
};
|
||||
|
||||
MotorController::MotorController(int motorPin)
|
||||
: motorPWMPin(motorPin), currentSpeed(0) {
|
||||
loadDefaults();
|
||||
pinMode(motorPWMPin, OUTPUT);
|
||||
stopMotor();
|
||||
}
|
||||
|
||||
void MotorController::loadDefaults() {
|
||||
config = defaultConfig;
|
||||
}
|
||||
|
||||
void MotorController::setTargetSpeed(int targetSpeedPercent) {
|
||||
targetSpeedPercent = constrain(targetSpeedPercent, 0, 100);
|
||||
int tableIndex = map(targetSpeedPercent, 0, 100, 0, MotorConfig::lookupTableSize - 1);
|
||||
uint8_t targetPWM = config.lookupTable[tableIndex];
|
||||
uint8_t adjustedPWM = applyDynamicResponse(targetPWM);
|
||||
setPWM(adjustedPWM);
|
||||
currentSpeed = targetSpeedPercent;
|
||||
}
|
||||
|
||||
int MotorController::getSpeed() const {
|
||||
return currentSpeed;
|
||||
}
|
||||
|
||||
void MotorController::stopMotor() {
|
||||
setTargetSpeed(0);
|
||||
}
|
||||
|
||||
MotorConfig MotorController::getConfig() const {
|
||||
return config;
|
||||
}
|
||||
|
||||
void MotorController::setConfig(const MotorConfig &newConfig) {
|
||||
config = newConfig;
|
||||
}
|
||||
|
||||
void MotorController::setPWM(uint8_t pwmValue) {
|
||||
uint8_t constrainedPWM = constrain(pwmValue, config.minPWM, config.maxPWM);
|
||||
analogWrite(motorPWMPin, config.inverted ? 255 - constrainedPWM : constrainedPWM);
|
||||
}
|
||||
|
||||
int MotorController::applyDynamicResponse(int targetValue) {
|
||||
static int smoothedValue = 0;
|
||||
int delta = targetValue - smoothedValue;
|
||||
int step = delta / config.responseSpeed;
|
||||
smoothedValue += step;
|
||||
return smoothedValue;
|
||||
}
|
39
src/MotorController.h
Normal file
39
src/MotorController.h
Normal file
@ -0,0 +1,39 @@
|
||||
// MotorController.h
|
||||
#ifndef MOTORCONTROLLER_H
|
||||
#define MOTORCONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// Motor configuration structure
|
||||
struct MotorConfig {
|
||||
uint8_t minPWM;
|
||||
uint8_t maxPWM;
|
||||
bool inverted;
|
||||
int responseSpeed;
|
||||
static const int lookupTableSize = 10;
|
||||
uint8_t lookupTable[lookupTableSize];
|
||||
};
|
||||
|
||||
class MotorController {
|
||||
private:
|
||||
int motorPWMPin;
|
||||
int currentSpeed;
|
||||
MotorConfig config;
|
||||
|
||||
int applyDynamicResponse(int targetValue);
|
||||
void setPWM(uint8_t pwmValue);
|
||||
|
||||
public:
|
||||
MotorController(int motorPin);
|
||||
|
||||
void stopMotor();
|
||||
void setTargetSpeed(int targetSpeedPercent);
|
||||
int getSpeed() const;
|
||||
|
||||
MotorConfig getConfig() const;
|
||||
void setConfig(const MotorConfig &newConfig);
|
||||
void loadDefaults();
|
||||
|
||||
};
|
||||
|
||||
#endif // MOTORCONTROLLER_H
|
156
src/PedalController.cpp
Normal file
156
src/PedalController.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
// PedalController.cpp
|
||||
#include "PedalController.h"
|
||||
|
||||
const int minMin = 50; // Minimum allowed raw value for calibration
|
||||
const int maxMin = 200; // Maximum allowed raw value for calibration
|
||||
const int minMax = 800; // Minimum allowed maximum value for calibration
|
||||
const int maxMax = 1000; // Maximum allowed raw value for calibration
|
||||
|
||||
const PedalConfig defaultConfig = {
|
||||
.minRaw = 0,
|
||||
.maxRaw = 1023,
|
||||
.calibrated = false
|
||||
};
|
||||
|
||||
PedalController::PedalController(int pin)
|
||||
: pedalPin(pin)
|
||||
{
|
||||
loadDefaults();
|
||||
pinMode(pedalPin, INPUT);
|
||||
}
|
||||
|
||||
void PedalController::loadDefaults()
|
||||
{
|
||||
config = defaultConfig;
|
||||
}
|
||||
|
||||
int PedalController::applySmoothing(int rawValue)
|
||||
{
|
||||
filteredValue = (filteredValue * (config.filterStrength - 1) + rawValue) / config.filterStrength;
|
||||
return filteredValue;
|
||||
}
|
||||
|
||||
CalibrationState PedalController::autoCalibrate(bool reset)
|
||||
{
|
||||
static int step = 0;
|
||||
static unsigned long lastChangeTime = 0;
|
||||
static int previousValue = 0;
|
||||
static CalibrationState errorState = IDLE;
|
||||
|
||||
if (reset)
|
||||
{
|
||||
step = 0;
|
||||
config.minRaw = 1023;
|
||||
config.maxRaw = 0;
|
||||
lastChangeTime = millis();
|
||||
config.calibrated = false;
|
||||
errorState = IDLE;
|
||||
Serial.println("Calibration reset.");
|
||||
return IDLE;
|
||||
}
|
||||
|
||||
unsigned long currentTime = millis();
|
||||
int rawValue = applySmoothing(analogRead(pedalPin));
|
||||
|
||||
switch (step)
|
||||
{
|
||||
case 0: // Initial state: wait for pedal release
|
||||
if (rawValue == previousValue && currentTime - lastChangeTime > 2000)
|
||||
{
|
||||
if (rawValue >= minMin && rawValue <= maxMin)
|
||||
{
|
||||
config.minRaw = rawValue;
|
||||
step++;
|
||||
lastChangeTime = currentTime;
|
||||
errorState = RUNNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorState = ERROR;
|
||||
}
|
||||
}
|
||||
else if (rawValue != previousValue)
|
||||
{
|
||||
lastChangeTime = currentTime;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Wait for pedal full press
|
||||
if (rawValue == previousValue && currentTime - lastChangeTime > 2000)
|
||||
{
|
||||
if (rawValue >= minMax && rawValue <= maxMax)
|
||||
{
|
||||
config.maxRaw = rawValue;
|
||||
step++;
|
||||
lastChangeTime = currentTime;
|
||||
errorState = RUNNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorState = ERROR;
|
||||
}
|
||||
}
|
||||
else if (rawValue != previousValue)
|
||||
{
|
||||
lastChangeTime = currentTime;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Validate calibration
|
||||
if (config.maxRaw > config.minRaw + 100)
|
||||
{ // Ensure valid range
|
||||
step++;
|
||||
config.calibrated = true;
|
||||
errorState = SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorState = ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errorState = IDLE;
|
||||
step = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
previousValue = rawValue;
|
||||
return errorState;
|
||||
}
|
||||
|
||||
int PedalController::getPedal()
|
||||
{
|
||||
if (!config.calibrated || autoCalibrate(false) != IDLE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rawValue = applySmoothing(analogRead(pedalPin));
|
||||
if (rawValue < config.minRaw || rawValue > config.maxRaw)
|
||||
{
|
||||
return 0; // Out of bounds
|
||||
}
|
||||
|
||||
return map(rawValue, config.minRaw, config.maxRaw, 0, 100);
|
||||
}
|
||||
|
||||
CalibrationState PedalController::getStatus()
|
||||
{
|
||||
return autoCalibrate(false);
|
||||
}
|
||||
|
||||
int PedalController::getRawValue()
|
||||
{
|
||||
return analogRead(pedalPin);
|
||||
}
|
||||
|
||||
PedalConfig PedalController::getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
void PedalController::setConfig(const PedalConfig &newConfig)
|
||||
{
|
||||
config = newConfig;
|
||||
}
|
46
src/PedalController.h
Normal file
46
src/PedalController.h
Normal file
@ -0,0 +1,46 @@
|
||||
// PedalController.h
|
||||
#ifndef PEDALCONTROLLER_H
|
||||
#define PEDALCONTROLLER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// Calibration state enumeration
|
||||
enum CalibrationState {
|
||||
IDLE,
|
||||
RUNNING,
|
||||
SUCCESS,
|
||||
ERROR
|
||||
};
|
||||
|
||||
// Pedal configuration structure
|
||||
struct PedalConfig {
|
||||
int minRaw;
|
||||
int maxRaw;
|
||||
bool calibrated;
|
||||
int filterStrength;
|
||||
};
|
||||
|
||||
class PedalController {
|
||||
private:
|
||||
int pedalPin;
|
||||
int filteredValue;
|
||||
PedalConfig config;
|
||||
|
||||
int applySmoothing(int rawValue);
|
||||
int getRawValue();
|
||||
|
||||
public:
|
||||
PedalController(int pin);
|
||||
|
||||
CalibrationState autoCalibrate(bool reset);
|
||||
CalibrationState getStatus();
|
||||
|
||||
int getPedal();
|
||||
|
||||
PedalConfig getConfig();
|
||||
void setConfig(const PedalConfig &newConfig);
|
||||
void loadDefaults();
|
||||
|
||||
};
|
||||
|
||||
#endif // PEDALCONTROLLER_H
|
254
src/main.cpp
Normal file
254
src/main.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
#include "MotorController.h"
|
||||
#include "PedalController.h"
|
||||
|
||||
// OLED display setup
|
||||
#define OLED_RESET -1
|
||||
#define SCREEN_WIDTH 128
|
||||
#define SCREEN_HEIGHT 64
|
||||
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||
|
||||
// Pin definitions
|
||||
const int hallSensor = 2; // Hall sensor input
|
||||
const int encoderPinA = 3; // Encoder pin A
|
||||
const int encoderPinB = 4; // Encoder pin B
|
||||
const int encoderButton = 5; // Encoder button
|
||||
const int motorPin = 9; // Motor PWM pin
|
||||
const int pedalPin = A0; // Pedal input pin
|
||||
|
||||
// Global objects
|
||||
MotorController motor(motorPin); // Motor control object
|
||||
PedalController pedal(pedalPin); // Pedal input object
|
||||
|
||||
// Combined settings structure
|
||||
struct Settings {
|
||||
MotorConfig motorConfig;
|
||||
PedalConfig pedalConfig;
|
||||
uint8_t checksum;
|
||||
};
|
||||
|
||||
Settings settings;
|
||||
bool autoCalibrating = false;
|
||||
bool serialControlEnabled = false;
|
||||
CalibrationState lastCalibrationState = IDLE;
|
||||
|
||||
// Function prototypes
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
uint8_t calculateChecksum(const Settings &s);
|
||||
void handleEncoder();
|
||||
void handleEncoderButton();
|
||||
void updateDisplay();
|
||||
void handleSerialInput();
|
||||
void configurePWMFrequency();
|
||||
void stopMotorAtNeedleUp();
|
||||
void printHelp();
|
||||
|
||||
void setup() {
|
||||
// Initialize pins
|
||||
pinMode(hallSensor, INPUT);
|
||||
pinMode(encoderPinA, INPUT_PULLUP);
|
||||
pinMode(encoderPinB, INPUT_PULLUP);
|
||||
pinMode(encoderButton, INPUT_PULLUP);
|
||||
|
||||
// Configure PWM frequency
|
||||
configurePWMFrequency();
|
||||
|
||||
// Attach interrupts for encoder
|
||||
attachInterrupt(digitalPinToInterrupt(encoderPinA), handleEncoder, CHANGE);
|
||||
attachInterrupt(digitalPinToInterrupt(encoderPinB), handleEncoder, CHANGE);
|
||||
attachInterrupt(digitalPinToInterrupt(encoderButton), handleEncoderButton, FALLING);
|
||||
|
||||
// Initialize serial and load settings
|
||||
Serial.begin(9600);
|
||||
loadSettings();
|
||||
|
||||
// Initialize OLED display
|
||||
// if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
|
||||
// Serial.println(F("SSD1306 allocation failed"));
|
||||
// }
|
||||
// display.clearDisplay();
|
||||
// display.display();
|
||||
|
||||
printHelp();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Handle serial input for debugging and manual control
|
||||
handleSerialInput();
|
||||
|
||||
if (autoCalibrating) {
|
||||
CalibrationState currentState = pedal.autoCalibrate(false);
|
||||
if (currentState != lastCalibrationState) {
|
||||
lastCalibrationState = currentState;
|
||||
switch (currentState) {
|
||||
case RUNNING:
|
||||
Serial.println("Calibration running...");
|
||||
break;
|
||||
case SUCCESS:
|
||||
Serial.println("Auto-calibration completed.");
|
||||
break;
|
||||
case ERROR:
|
||||
Serial.println("Auto-calibration failed.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
motor.setTargetSpeed(0); // Ensure motor stays off during calibration
|
||||
} else {
|
||||
int pedalValue = serialControlEnabled ? 0 : pedal.getPedal();
|
||||
motor.setTargetSpeed(pedalValue);
|
||||
}
|
||||
|
||||
// Update display
|
||||
// updateDisplay();
|
||||
|
||||
delay(10); // Short delay for stability
|
||||
}
|
||||
|
||||
void stopMotorAtNeedleUp() {
|
||||
motor.stopMotor();
|
||||
delay(100); // Stabilize
|
||||
}
|
||||
|
||||
void loadSettings() {
|
||||
EEPROM.get(0, settings);
|
||||
|
||||
// Validate checksum
|
||||
if (calculateChecksum(settings) != settings.checksum) {
|
||||
Serial.println("Invalid settings checksum, loading defaults.");
|
||||
motor.loadDefaults();
|
||||
pedal.autoCalibrate(true);
|
||||
|
||||
settings.motorConfig = motor.getConfig();
|
||||
settings.pedalConfig = pedal.getConfig();
|
||||
settings.checksum = calculateChecksum(settings);
|
||||
|
||||
saveSettings();
|
||||
} else {
|
||||
motor.setConfig(settings.motorConfig);
|
||||
pedal.setConfig(settings.pedalConfig);
|
||||
Serial.println("Settings loaded from EEPROM.");
|
||||
}
|
||||
}
|
||||
|
||||
void saveSettings() {
|
||||
settings.motorConfig = motor.getConfig();
|
||||
settings.pedalConfig = pedal.getConfig();
|
||||
settings.checksum = calculateChecksum(settings);
|
||||
|
||||
EEPROM.put(0, settings);
|
||||
Serial.println("Settings saved to EEPROM.");
|
||||
}
|
||||
|
||||
uint8_t calculateChecksum(const Settings &s) {
|
||||
uint8_t sum = 0;
|
||||
const uint8_t *data = reinterpret_cast<const uint8_t *>(&s);
|
||||
for (size_t i = 0; i < sizeof(Settings) - 1; i++) {
|
||||
sum ^= data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void handleEncoder() {
|
||||
static uint8_t lastState = 0;
|
||||
uint8_t currentState = (digitalRead(encoderPinA) << 1) | digitalRead(encoderPinB);
|
||||
if ((lastState == 0b00 && currentState == 0b01) ||
|
||||
(lastState == 0b01 && currentState == 0b11) ||
|
||||
(lastState == 0b11 && currentState == 0b10) ||
|
||||
(lastState == 0b10 && currentState == 0b00)) {
|
||||
// Increment
|
||||
} else if ((lastState == 0b00 && currentState == 0b10) ||
|
||||
(lastState == 0b10 && currentState == 0b11) ||
|
||||
(lastState == 0b11 && currentState == 0b01) ||
|
||||
(lastState == 0b01 && currentState == 0b00)) {
|
||||
// Decrement
|
||||
}
|
||||
lastState = currentState;
|
||||
}
|
||||
|
||||
void handleEncoderButton() {
|
||||
// Handle encoder button press
|
||||
}
|
||||
|
||||
void updateDisplay() {
|
||||
display.clearDisplay();
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(SSD1306_WHITE);
|
||||
|
||||
display.setCursor(0, 0);
|
||||
display.print("Pedal: ");
|
||||
display.println(pedal.getPedal());
|
||||
|
||||
display.display();
|
||||
}
|
||||
|
||||
void handleSerialInput() {
|
||||
if (Serial.available()) {
|
||||
char input = Serial.read();
|
||||
switch (input) {
|
||||
case 'c':
|
||||
Serial.println("Starting auto-calibration...");
|
||||
pedal.autoCalibrate(true);
|
||||
autoCalibrating = true;
|
||||
lastCalibrationState = IDLE; // Reset state tracking
|
||||
break;
|
||||
case 'x':
|
||||
Serial.println("Stopping auto-calibration or serial control.");
|
||||
autoCalibrating = false;
|
||||
serialControlEnabled = false;
|
||||
motor.stopMotor();
|
||||
break;
|
||||
case 'r':
|
||||
Serial.println("Loading defaults.");
|
||||
motor.loadDefaults();
|
||||
pedal.loadDefaults();
|
||||
break;
|
||||
case 's':
|
||||
Serial.println("Saving settings to EEPROM.");
|
||||
saveSettings();
|
||||
break;
|
||||
case 'l':
|
||||
Serial.println("Loading settings from EEPROM.");
|
||||
loadSettings();
|
||||
break;
|
||||
case 'h':
|
||||
printHelp();
|
||||
break;
|
||||
case '+':
|
||||
serialControlEnabled = true;
|
||||
motor.setTargetSpeed(motor.getSpeed() + 1);
|
||||
Serial.print("Increased Speed to: ");
|
||||
Serial.println(motor.getSpeed());
|
||||
break;
|
||||
case '-':
|
||||
serialControlEnabled = true;
|
||||
motor.setTargetSpeed(motor.getSpeed() - 1);
|
||||
Serial.print("Decreased Speed to: ");
|
||||
Serial.println(motor.getSpeed());
|
||||
break;
|
||||
}
|
||||
Serial.println(input);
|
||||
}
|
||||
}
|
||||
|
||||
void printHelp() {
|
||||
Serial.println("Available commands:");
|
||||
Serial.println("c - Start auto-calibration");
|
||||
Serial.println("x - Stop auto-calibration or serial control");
|
||||
Serial.println("r - Load defaults");
|
||||
Serial.println("s - Save settings to EEPROM");
|
||||
Serial.println("l - Load settings from EEPROM");
|
||||
Serial.println("h - Show this help");
|
||||
Serial.println("+ - Increment PWM");
|
||||
Serial.println("- - Decrement PWM");
|
||||
}
|
||||
|
||||
void configurePWMFrequency() {
|
||||
// Configure Timer1 for higher PWM frequency (e.g., ~8 kHz)
|
||||
TCCR1B = (TCCR1B & 0b11111000) | 0x01; // Set prescaler to 1
|
||||
}
|
11
test/README
Normal file
11
test/README
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
Loading…
x
Reference in New Issue
Block a user