mirror of
https://github.com/Vale54321/schafkop-neu.git
synced 2025-12-16 11:49:34 +01:00
refactor: structure pico project
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
// ...existing code...
|
||||
class Stepper {
|
||||
protected:
|
||||
int steps_per_rev;
|
||||
public:
|
||||
virtual void step(int steps, bool direction) = 0;
|
||||
void step_rev(int revs, bool direction){
|
||||
step(steps_per_rev*revs, direction);
|
||||
}
|
||||
int get_steps_per_rev(){
|
||||
return steps_per_rev;
|
||||
}
|
||||
virtual ~Stepper() {}
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "Stepper.h"
|
||||
#include <array>
|
||||
class ULN2003Stepper : public Stepper {
|
||||
private:
|
||||
std::array<uint8_t, 4> pins;
|
||||
static constexpr int steps_per_seq = 8;
|
||||
const uint8_t sequence[8][4] = {
|
||||
{1, 0, 0, 0},
|
||||
{1, 1, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 1, 1, 0},
|
||||
{0, 0, 1, 0},
|
||||
{0, 0, 1, 1},
|
||||
{0, 0, 0, 1},
|
||||
{1, 0, 0, 1}
|
||||
};
|
||||
int step_delay_us = 5000;
|
||||
public:
|
||||
ULN2003Stepper(std::array<uint8_t, 4> pins, int rev_steps) : pins(pins) {
|
||||
steps_per_rev = rev_steps;
|
||||
for (auto pin : pins) {
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
}
|
||||
void step(int steps, bool direction) override {
|
||||
for (int i = 0; i < steps; ++i) {
|
||||
int seq_idx = direction ? (i % steps_per_seq) : (steps_per_seq - 1 - (i % steps_per_seq));
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
digitalWrite(pins[j], sequence[seq_idx][j]);
|
||||
}
|
||||
delayMicroseconds(step_delay_us);
|
||||
}
|
||||
}
|
||||
void setSpeed(int delay_us) {
|
||||
step_delay_us = delay_us;
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <Arduino.h>
|
||||
#include "Stepper.h"
|
||||
#include "ULN2003Stepper.h"
|
||||
#include <Stepper.h>
|
||||
#include <ULN2003Stepper.h>
|
||||
|
||||
#ifndef LED_BUILTIN
|
||||
#define LED_BUILTIN 25
|
||||
@@ -16,12 +16,10 @@ public:
|
||||
|
||||
Serial.begin(baud);
|
||||
|
||||
int revSteps = driver1.get_steps_per_rev();
|
||||
Serial.print("EVENT:START STEPS_PER_REV ");
|
||||
Serial.println(revSteps);
|
||||
|
||||
waitForHost(1500);
|
||||
logStartup();
|
||||
|
||||
// Startup indication
|
||||
for(int i=0;i<3;i++) blink(60,100);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@@ -31,7 +29,11 @@ public:
|
||||
private:
|
||||
String inputBuffer;
|
||||
|
||||
enum class CmdType { PING, STEP, SPEED, UNKNOWN };
|
||||
struct CommandHandler {
|
||||
const char* name;
|
||||
void (SchafkopfSerialApp::*fn)(const String &args);
|
||||
};
|
||||
static const CommandHandler commandTable[]; // defined after class
|
||||
|
||||
void waitForHost(unsigned long timeoutMs){
|
||||
unsigned long start = millis();
|
||||
@@ -45,15 +47,10 @@ private:
|
||||
if(offMs) delay(offMs);
|
||||
}
|
||||
|
||||
void logStartup(){
|
||||
Serial.println(F("HELLO START"));
|
||||
for(int i=0;i<3;i++) blink(60,100);
|
||||
}
|
||||
|
||||
void pollSerial(){
|
||||
while(Serial.available()){
|
||||
char c = Serial.read();
|
||||
if(c=='\r') continue; // ignore CR
|
||||
if(c=='\r') continue;
|
||||
if(c=='\n') {
|
||||
processLine(inputBuffer);
|
||||
inputBuffer = "";
|
||||
@@ -66,17 +63,21 @@ private:
|
||||
void processLine(const String &raw){
|
||||
String line = raw;
|
||||
line.trim();
|
||||
|
||||
if(!line.length()) return;
|
||||
|
||||
String cmdToken = firstToken(line);
|
||||
String rest = remainingAfterFirst(line);
|
||||
CmdType type = classify(cmdToken);
|
||||
handleCommand(type, cmdToken, rest);
|
||||
|
||||
cmdToken.toUpperCase();
|
||||
dispatchCommand(cmdToken, rest);
|
||||
}
|
||||
|
||||
static String firstToken(const String &line){
|
||||
int sp = line.indexOf(' ');
|
||||
return (sp==-1)? line : line.substring(0, sp);
|
||||
}
|
||||
|
||||
static String remainingAfterFirst(const String &line){
|
||||
int sp = line.indexOf(' ');
|
||||
if (sp==-1) return String("");
|
||||
@@ -85,67 +86,68 @@ private:
|
||||
return r;
|
||||
}
|
||||
|
||||
CmdType classify(String token){
|
||||
token.toUpperCase();
|
||||
if(token==F("PING")) return CmdType::PING;
|
||||
if(token==F("STEP")) return CmdType::STEP;
|
||||
if(token==F("SPEED")) return CmdType::SPEED;
|
||||
return CmdType::UNKNOWN;
|
||||
void dispatchCommand(const String &uppercaseToken, const String &args){
|
||||
for(size_t i=0; commandTable[i].name != nullptr; ++i){
|
||||
if(uppercaseToken.equals(commandTable[i].name)){
|
||||
(this->*commandTable[i].fn)(args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Serial.print(F("ERR:UNKNOWN COMMAND '")); Serial.print(uppercaseToken); Serial.println("'");
|
||||
blink(20);
|
||||
}
|
||||
|
||||
void handleCommand(CmdType type, const String &token, const String &args){
|
||||
switch(type){
|
||||
case CmdType::PING: {
|
||||
Serial.println(F("PONG"));
|
||||
blink();
|
||||
break; }
|
||||
case CmdType::STEP: {
|
||||
// Expected: STEP <steps> <dir>
|
||||
int steps = -1; int dir = -1;
|
||||
if(parseStepArgs(args, steps, dir)) {
|
||||
Serial.print(F("STEP: moving ")); Serial.print(steps); Serial.print(F(" dir=")); Serial.println(dir);
|
||||
driver1.step(steps, dir!=0);
|
||||
blink(60);
|
||||
} else {
|
||||
Serial.println(F("ERR:STEP usage STEP <steps> <0|1>"));
|
||||
blink(20);
|
||||
}
|
||||
break; }
|
||||
case CmdType::SPEED: {
|
||||
int delayUs = args.toInt();
|
||||
if(delayUs > 0) {
|
||||
driver1.setSpeed(delayUs);
|
||||
Serial.print(F("SPEED: set delay_us=")); Serial.println(delayUs);
|
||||
blink();
|
||||
} else {
|
||||
Serial.println(F("ERR:SPEED usage SPEED <positive_delay_us>"));
|
||||
blink(20);
|
||||
}
|
||||
break; }
|
||||
case CmdType::UNKNOWN: {
|
||||
Serial.print(F("ERR:UNKNOWN COMMAND '")); Serial.print(token); Serial.println("'");
|
||||
blink(20);
|
||||
break; }
|
||||
default: {
|
||||
Serial.println(F("ERR:UNHANDLED"));
|
||||
blink(20);
|
||||
break; }
|
||||
// ---- COMMANDS ----
|
||||
void cmdHealthcheck(const String &){
|
||||
Serial.println(F("OK"));
|
||||
blink();
|
||||
}
|
||||
|
||||
void cmdStep(const String &args){
|
||||
double steps = -1; int dir = -1;
|
||||
if(parseStepArgs(args, steps, dir)) {
|
||||
Serial.print(F("STEP: moving ")); Serial.print(steps); Serial.print(F(" dir=")); Serial.println(dir);
|
||||
driver1.step_rev(steps, dir!=0);
|
||||
blink(60);
|
||||
} else {
|
||||
Serial.println(F("ERR:STEP usage STEP <revs> <0|1>"));
|
||||
blink(20);
|
||||
}
|
||||
}
|
||||
// Helpers for parsing arguments
|
||||
bool parseStepArgs(const String &args, int &steps, int &dir){
|
||||
|
||||
void cmdSpeed(const String &args){
|
||||
int delayUs = args.toInt();
|
||||
if(delayUs > 0) {
|
||||
driver1.setStepDelay(delayUs);
|
||||
Serial.print(F("SPEED: set delay_us=")); Serial.println(delayUs);
|
||||
blink();
|
||||
} else {
|
||||
Serial.println(F("ERR:SPEED usage SPEED <positive_delay_us>"));
|
||||
blink(20);
|
||||
}
|
||||
}
|
||||
|
||||
bool parseStepArgs(const String &args, double &steps, int &dir){
|
||||
int sp = args.indexOf(' ');
|
||||
if(sp == -1) return false;
|
||||
String a = args.substring(0, sp); a.trim();
|
||||
String b = args.substring(sp+1); b.trim();
|
||||
if(!a.length() || !b.length()) return false;
|
||||
steps = a.toInt(); dir = b.toInt();
|
||||
steps = a.toDouble(); dir = b.toInt();
|
||||
if(steps <= 0) return false;
|
||||
if(!(dir==0 || dir==1)) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// ---- COMMAND TABLE ----
|
||||
const SchafkopfSerialApp::CommandHandler SchafkopfSerialApp::commandTable[] = {
|
||||
{"HEALTHCHECK", &SchafkopfSerialApp::cmdHealthcheck},
|
||||
{"STEP", &SchafkopfSerialApp::cmdStep},
|
||||
{"SPEED", &SchafkopfSerialApp::cmdSpeed},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
SchafkopfSerialApp app;
|
||||
|
||||
void setup(){ app.begin(); }
|
||||
|
||||
Reference in New Issue
Block a user