STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1// Install: ESP32Encoder library by madhephaestus
2
3#include <Arduino.h>
4#include <ESP32Encoder.h>
5
6#include <cstdio>
7#include <cstring>
8
9#include "EthernetHandler.h"
10
11ESP32Encoder enc;
12
13// L298N pins (your latest wiring)
14const int ENA = 25; // PWM
15const int IN1 = 23;
16const int IN2 = 5;
17
18// Encoder pins (your latest wiring)
19const int ENCA = 19;
20const int ENCB = 21;
21
22// ---- Tuning / mech constants ----
23float Kp = 0.0015f; // start here; raise if too slow, lower if oscillates
24const int CPR_4X_MOTOR =
25 64; // encoder counts per MOTOR rev at 4x (set true value)
26const float GEAR_RATIO = 210.0f; // internal gearbox ratio you reported
28
29// PWM setup
30const int PWM_CH = 0;
31const int PWM_FREQ = 8000;
32const int PWM_BITS = 8;
33const int PWM_MAX = (1 << PWM_BITS) - 1;
34const int PWM_MIN = 45; // deadband to overcome L298N + gearmotor friction
35
36// Control state
37volatile int dir_sign = +1; // set by autoPolarityCal()
38long target = 1000; // counts
39uint32_t toggle_t0 = 0;
40uint32_t print_t0 = 0;
41
42void motorCoast() {
45 ledcWrite(PWM_CH, 0);
46}
47
48void motorDrive(float u) {
49 // u in [-1, 1] after dir_sign applied
50 u = constrain(u, -1.0f, 1.0f);
51 int pwm = 0;
52
53 if (fabs(u) < 1e-3f) {
54 motorCoast();
55 return;
56 }
57
58 if (u > 0) {
61 pwm = PWM_MIN + (int)((PWM_MAX - PWM_MIN) * u);
62 } else {
65 pwm = PWM_MIN + (int)((PWM_MAX - PWM_MIN) * (-u));
66 }
67 ledcWrite(PWM_CH, pwm);
68}
69
70// One-shot polarity calibration: apply a small forward nudge and measure
71// Δcounts
73 Serial.println("Auto-polarity: nudging forward to detect sign...");
74 enc.clearCount();
75
76 // gentle forward nudge
79 ledcWrite(PWM_CH, 60); // small PWM above deadband
80 delay(150);
81 motorCoast();
82
83 long dpos = enc.getCount();
84 if (dpos < 0) {
85 dir_sign = -1;
86 Serial.println("Auto-polarity: inverted (dir_sign = -1).");
87 } else {
88 dir_sign = +1;
89 Serial.println("Auto-polarity: OK (dir_sign = +1).");
90 }
91
92 // Reset reference after calibration
93 enc.clearCount();
94}
95
96void setup() {
97 Serial.begin(115200);
98 delay(200);
99
100 EthernetConfig ethConfig{};
101 ethConfig.pins = {7, 41, 13, 6};
102 ethConfig.staticIP = IPAddress(192, 168, 2, 103);
103 ethConfig.gateway = IPAddress(192, 168, 2, 1);
104 ethConfig.subnet = IPAddress(255, 255, 255, 0);
105 ethConfig.dns = IPAddress(192, 168, 2, 1);
106 ethConfig.receiverIP = IPAddress(192, 168, 2, 1);
107 ethConfig.receiverPort = 5006;
108 ethConfig.localPort = 5005;
109 EthernetInit(ethConfig);
110 Serial.print("Motor Ethernet IP: ");
111 Serial.println(getLocalIP());
112
113 // Encoder
114 enc.attachFullQuad(ENCA, ENCB);
115 enc.clearCount();
116
117 // L298N control pins + PWM
120 ledcSetup(PWM_CH, PWM_FREQ, PWM_BITS);
121 ledcAttachPin(ENA, PWM_CH);
122 motorCoast();
123
124 Serial.println(
125 "Ready. Calibrating direction, then toggling 0 <-> +1000 counts.");
126 autoPolarityCal(); // determine dir_sign before control starts
127}
128
129void loop() {
130 long pos = enc.getCount();
131 float err = (float)(target - pos);
132
133 float u = dir_sign * Kp * err;
134 u = constrain(u, -1.0f, 1.0f);
135 motorDrive(u);
136
137 // Telemetry
138 if (millis() - print_t0 > 200) {
139 print_t0 = millis();
140 float deg = CPR_OUT > 0 ? (pos * 360.0f / CPR_OUT) : 0.0f;
141 int pwm_now = ledcRead(PWM_CH);
142 char msg[120];
143 int n = snprintf(msg, sizeof(msg),
144 "pos=%ld target=%ld err=%.0f dir=%d pwm=%d deg=%.1f",
145 pos, target, err, dir_sign, pwm_now, deg);
146 Serial.println(msg);
147 if (ethernetReady()) {
148 size_t payloadLen = (n < 0) ? strlen(msg)
149 : ((n >= static_cast<int>(sizeof(msg)))
150 ? sizeof(msg) - 1
151 : static_cast<size_t>(n));
152 sendPacket(reinterpret_cast<const uint8_t*>(msg), payloadLen);
153 }
154 }
155
156 // Toggle target every 3 s
157 if (millis() - toggle_t0 > 3000) {
158 toggle_t0 = millis();
159 target = (target == 0) ? 1000 : 0;
160 char toggleMsg[48];
161 int n = snprintf(toggleMsg, sizeof(toggleMsg), "New target: %ld counts",
162 target);
163 Serial.println(toggleMsg);
164 if (ethernetReady()) {
165 size_t payloadLen =
166 (n < 0) ? strlen(toggleMsg)
167 : ((n >= static_cast<int>(sizeof(toggleMsg)))
168 ? sizeof(toggleMsg) - 1
169 : static_cast<size_t>(n));
170 sendPacket(reinterpret_cast<const uint8_t*>(toggleMsg), payloadLen);
171 }
172 }
173
174 delay(5);
175}
static SerialStub Serial
Definition Arduino.h:128
#define HIGH
Definition Arduino.h:19
void pinMode(int, int)
Definition Arduino.h:46
#define OUTPUT
Definition Arduino.h:22
unsigned long millis()
Definition Arduino.h:29
#define LOW
Definition Arduino.h:20
void digitalWrite(int, int)
Definition Arduino.h:48
void EthernetInit(const EthernetConfig &config)
IPAddress getLocalIP()
bool ethernetReady()
void sendPacket(const uint8_t *data, size_t len)
const int IPAddress
void delay(int ms)
void setup()
Definition main.cpp:142
void loop()
Definition main.cpp:201
void motorDrive(float u)
Definition main.cpp:48
const int IN1
Definition main.cpp:15
float Kp
Definition main.cpp:23
const int PWM_FREQ
Definition main.cpp:31
const int CPR_4X_MOTOR
Definition main.cpp:24
long target
Definition main.cpp:38
volatile int dir_sign
Definition main.cpp:37
const int PWM_CH
Definition main.cpp:30
const float GEAR_RATIO
Definition main.cpp:26
const float CPR_OUT
Definition main.cpp:27
const int IN2
Definition main.cpp:16
uint32_t print_t0
Definition main.cpp:40
void autoPolarityCal()
Definition main.cpp:72
ESP32Encoder enc
Definition main.cpp:11
const int PWM_MIN
Definition main.cpp:34
const int PWM_MAX
Definition main.cpp:33
const int PWM_BITS
Definition main.cpp:32
const int ENA
Definition main.cpp:14
uint32_t toggle_t0
Definition main.cpp:39
const int ENCA
Definition main.cpp:19
const int ENCB
Definition main.cpp:20
void motorCoast()
Definition main.cpp:42
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:24474
EthernetPins pins
IPAddress receiverIP
uint16_t receiverPort