flame-wro-fe 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ ; PlatformIO Project Configuration File
2
+ ;
3
+ ; Build options: build flags, source filter
4
+ ; Upload options: custom upload port, speed and extra flags
5
+ ; Library options: dependencies, extra library storages
6
+ ; Advanced options: extra scripting
7
+ ;
8
+ ; Please visit documentation for the other options and examples
9
+ ; https://docs.platformio.org/page/projectconf.html
10
+
11
+ [env:nanoatmega328new]
12
+ platform = atmelavr
13
+ board = nanoatmega328new
14
+ framework = arduino
15
+ lib_deps = arduino-libraries/Servo@^1.2.2
16
+ monitor_speed = 9600
@@ -0,0 +1,276 @@
1
+ #include <Arduino.h>
2
+ #include <Servo.h>
3
+
4
+ // Defaults match your original wiring.
5
+ constexpr uint8_t SERVO_PIN = 6;
6
+
7
+ // true: two PWM H-bridge inputs, like the original sketch: IN1=10, IN2=9
8
+ // false: one PWM/enable pin plus two direction pins
9
+ constexpr bool USE_TWO_PWM_MOTOR_DRIVER = true;
10
+ constexpr bool USE_SOFTWARE_PWM_FOR_TWO_PWM_DRIVER = true;
11
+ constexpr uint8_t MOTOR_IN1_PIN = 10;
12
+ constexpr uint8_t MOTOR_IN2_PIN = 9;
13
+ constexpr uint8_t MOTOR_PWM_PIN = 11;
14
+
15
+ // Set this to true if you wired a physical enable switch to ENABLE_PIN.
16
+ constexpr bool USE_ENABLE_PIN = false;
17
+ constexpr uint8_t ENABLE_PIN = 7;
18
+
19
+ constexpr int SERVO_CENTER_DEG = 90;
20
+ constexpr int SERVO_MIN_DEG = 15;
21
+ constexpr int SERVO_MAX_DEG = 165;
22
+
23
+ constexpr int MOTOR_MAX_PWM = 200;
24
+ constexpr uint16_t MOTOR_RAMP_INTERVAL_MS = 20;
25
+ constexpr int MOTOR_RAMP_STEP = 2;
26
+ constexpr uint16_t SOFTWARE_PWM_PERIOD_US = 2000;
27
+ constexpr uint16_t COMMAND_TIMEOUT_MS = 1000;
28
+ constexpr size_t LINE_BUF_SIZE = 64;
29
+ constexpr bool PRINT_COMMAND_ACKS = false;
30
+
31
+ Servo steeringServo;
32
+
33
+ char lineBuf[LINE_BUF_SIZE];
34
+ size_t lineLen = 0;
35
+
36
+ int targetSpeed = 0;
37
+ int currentSpeed = 0;
38
+ int outputSpeed = 0;
39
+ int targetAngle = SERVO_CENTER_DEG;
40
+ unsigned long lastRampMs = 0;
41
+ unsigned long lastCommandMs = 0;
42
+
43
+ bool outputsEnabled() {
44
+ return !USE_ENABLE_PIN || digitalRead(ENABLE_PIN) == HIGH;
45
+ }
46
+
47
+ int clampInt(int value, int lo, int hi) {
48
+ return max(lo, min(hi, value));
49
+ }
50
+
51
+ void writeSteering(int absoluteAngleDeg) {
52
+ targetAngle = clampInt(absoluteAngleDeg, SERVO_MIN_DEG, SERVO_MAX_DEG);
53
+ steeringServo.write(targetAngle);
54
+ }
55
+
56
+ void writeMotorPwm(int speed) {
57
+ speed = clampInt(speed, -MOTOR_MAX_PWM, MOTOR_MAX_PWM);
58
+ if (!outputsEnabled()) {
59
+ speed = 0;
60
+ }
61
+
62
+ if (USE_TWO_PWM_MOTOR_DRIVER) {
63
+ if (USE_SOFTWARE_PWM_FOR_TWO_PWM_DRIVER) {
64
+ outputSpeed = speed;
65
+ if (speed == 0) {
66
+ digitalWrite(MOTOR_IN1_PIN, LOW);
67
+ digitalWrite(MOTOR_IN2_PIN, LOW);
68
+ }
69
+ return;
70
+ }
71
+
72
+ if (speed > 0) {
73
+ analogWrite(MOTOR_IN1_PIN, speed);
74
+ digitalWrite(MOTOR_IN2_PIN, LOW);
75
+ } else if (speed < 0) {
76
+ digitalWrite(MOTOR_IN1_PIN, LOW);
77
+ analogWrite(MOTOR_IN2_PIN, -speed);
78
+ } else {
79
+ analogWrite(MOTOR_IN1_PIN, 0);
80
+ analogWrite(MOTOR_IN2_PIN, 0);
81
+ digitalWrite(MOTOR_IN1_PIN, LOW);
82
+ digitalWrite(MOTOR_IN2_PIN, LOW);
83
+ }
84
+ return;
85
+ }
86
+
87
+ if (speed > 0) {
88
+ digitalWrite(MOTOR_IN1_PIN, HIGH);
89
+ digitalWrite(MOTOR_IN2_PIN, LOW);
90
+ } else if (speed < 0) {
91
+ digitalWrite(MOTOR_IN1_PIN, LOW);
92
+ digitalWrite(MOTOR_IN2_PIN, HIGH);
93
+ } else {
94
+ digitalWrite(MOTOR_IN1_PIN, LOW);
95
+ digitalWrite(MOTOR_IN2_PIN, LOW);
96
+ }
97
+
98
+ analogWrite(MOTOR_PWM_PIN, abs(speed));
99
+ }
100
+
101
+ void updateSoftwareMotorPwm() {
102
+ if (!USE_TWO_PWM_MOTOR_DRIVER || !USE_SOFTWARE_PWM_FOR_TWO_PWM_DRIVER) {
103
+ return;
104
+ }
105
+
106
+ int speed = clampInt(outputSpeed, -MOTOR_MAX_PWM, MOTOR_MAX_PWM);
107
+ if (speed == 0) {
108
+ digitalWrite(MOTOR_IN1_PIN, LOW);
109
+ digitalWrite(MOTOR_IN2_PIN, LOW);
110
+ return;
111
+ }
112
+
113
+ static unsigned long periodStartUs = micros();
114
+ unsigned long nowUs = micros();
115
+ unsigned long elapsed = nowUs - periodStartUs;
116
+ if (elapsed >= SOFTWARE_PWM_PERIOD_US) {
117
+ periodStartUs = nowUs;
118
+ elapsed = 0;
119
+ }
120
+
121
+ unsigned int dutyUs = (static_cast<unsigned long>(abs(speed)) * SOFTWARE_PWM_PERIOD_US) / MOTOR_MAX_PWM;
122
+ bool on = elapsed < dutyUs;
123
+ if (speed > 0) {
124
+ digitalWrite(MOTOR_IN1_PIN, on ? HIGH : LOW);
125
+ digitalWrite(MOTOR_IN2_PIN, LOW);
126
+ } else {
127
+ digitalWrite(MOTOR_IN1_PIN, LOW);
128
+ digitalWrite(MOTOR_IN2_PIN, on ? HIGH : LOW);
129
+ }
130
+ }
131
+
132
+ void stopMotor() {
133
+ targetSpeed = 0;
134
+ currentSpeed = 0;
135
+ writeMotorPwm(0);
136
+ }
137
+
138
+ void stopAll() {
139
+ writeSteering(SERVO_CENTER_DEG);
140
+ stopMotor();
141
+ }
142
+
143
+ void updateMotorRamp() {
144
+ unsigned long now = millis();
145
+ if (now - lastRampMs < MOTOR_RAMP_INTERVAL_MS) {
146
+ return;
147
+ }
148
+ lastRampMs = now;
149
+
150
+ if (currentSpeed < targetSpeed) {
151
+ currentSpeed = min(currentSpeed + MOTOR_RAMP_STEP, targetSpeed);
152
+ } else if (currentSpeed > targetSpeed) {
153
+ currentSpeed = max(currentSpeed - MOTOR_RAMP_STEP, targetSpeed);
154
+ }
155
+
156
+ writeMotorPwm(currentSpeed);
157
+ }
158
+
159
+ bool parseIntStrict(const char *text, int &outValue) {
160
+ char *endPtr = nullptr;
161
+ long value = strtol(text, &endPtr, 10);
162
+ if (text == endPtr) {
163
+ return false;
164
+ }
165
+ while (*endPtr == ' ' || *endPtr == '\t') {
166
+ endPtr++;
167
+ }
168
+ if (*endPtr != '\0') {
169
+ return false;
170
+ }
171
+ outValue = static_cast<int>(value);
172
+ return true;
173
+ }
174
+
175
+ void handleCommand(char *cmd) {
176
+ char *colon = strchr(cmd, ':');
177
+ if (colon) {
178
+ *colon = '\0';
179
+ }
180
+
181
+ char *name = cmd;
182
+ char *valueText = colon ? colon + 1 : nullptr;
183
+
184
+ while (*name == ' ' || *name == '\t') {
185
+ name++;
186
+ }
187
+
188
+ if (strcmp(name, "STOP") == 0) {
189
+ stopAll();
190
+ lastCommandMs = millis();
191
+ if (PRINT_COMMAND_ACKS) {
192
+ Serial.println("OK:STOP");
193
+ }
194
+ return;
195
+ }
196
+
197
+ if (!valueText) {
198
+ Serial.println("ERR:VALUE");
199
+ return;
200
+ }
201
+
202
+ int value = 0;
203
+ if (!parseIntStrict(valueText, value)) {
204
+ Serial.println("ERR:VALUE");
205
+ return;
206
+ }
207
+
208
+ if (strcmp(name, "STEER") == 0) {
209
+ writeSteering(value);
210
+ lastCommandMs = millis();
211
+ if (PRINT_COMMAND_ACKS) {
212
+ Serial.println("OK:STEER");
213
+ }
214
+ } else if (strcmp(name, "DRIVE") == 0) {
215
+ targetSpeed = clampInt(value, -MOTOR_MAX_PWM, MOTOR_MAX_PWM);
216
+ lastCommandMs = millis();
217
+ if (PRINT_COMMAND_ACKS) {
218
+ Serial.println("OK:DRIVE");
219
+ }
220
+ } else {
221
+ Serial.println("ERR:COMMAND");
222
+ }
223
+ }
224
+
225
+ void readSerialCommands() {
226
+ while (Serial.available() > 0) {
227
+ char c = static_cast<char>(Serial.read());
228
+
229
+ if (c == '\n') {
230
+ lineBuf[lineLen] = '\0';
231
+ handleCommand(lineBuf);
232
+ lineLen = 0;
233
+ } else if (c != '\r') {
234
+ if (lineLen < LINE_BUF_SIZE - 1) {
235
+ lineBuf[lineLen++] = c;
236
+ } else {
237
+ lineLen = 0;
238
+ Serial.println("ERR:OVERFLOW");
239
+ }
240
+ }
241
+ }
242
+ }
243
+
244
+ void setup() {
245
+ pinMode(MOTOR_IN1_PIN, OUTPUT);
246
+ pinMode(MOTOR_IN2_PIN, OUTPUT);
247
+ if (!USE_TWO_PWM_MOTOR_DRIVER) {
248
+ pinMode(MOTOR_PWM_PIN, OUTPUT);
249
+ }
250
+ if (USE_ENABLE_PIN) {
251
+ pinMode(ENABLE_PIN, INPUT_PULLUP);
252
+ }
253
+
254
+ steeringServo.attach(SERVO_PIN);
255
+ stopAll();
256
+
257
+ Serial.begin(9600);
258
+ delay(1500);
259
+ lastCommandMs = millis();
260
+ Serial.println("READY");
261
+ }
262
+
263
+ void loop() {
264
+ readSerialCommands();
265
+
266
+ if (millis() - lastCommandMs > COMMAND_TIMEOUT_MS) {
267
+ targetSpeed = 0;
268
+ }
269
+
270
+ if (!outputsEnabled()) {
271
+ targetSpeed = 0;
272
+ }
273
+
274
+ updateMotorRamp();
275
+ updateSoftwareMotorPwm();
276
+ }
package/index.js ADDED
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+
5
+ module.exports = {
6
+ raspberryPiSrcPath: path.join(__dirname, 'raspySrc'),
7
+ arduinoOutputProxyPath: path.join(__dirname, 'arduino', 'outputProxy')
8
+ };
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "flame-wro-fe",
3
+ "version": "1.0.0",
4
+ "description": "Flame WRO FE Raspberry runtime and Arduino output proxy sources",
5
+ "license": "Apache-2.0",
6
+ "files": [
7
+ "raspySrc/**/*",
8
+ "arduino/outputProxy/**/*",
9
+ "index.js",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "main": "index.js",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/berkemutluu/Flame-WRO-FE.git"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/berkemutluu/Flame-WRO-FE/issues"
20
+ },
21
+ "homepage": "https://github.com/berkemutluu/Flame-WRO-FE#readme",
22
+ "scripts": {
23
+ "pack:dry-run": "npm pack --dry-run"
24
+ },
25
+ "keywords": [
26
+ "wro",
27
+ "robotics",
28
+ "raspberry-pi",
29
+ "arduino"
30
+ ]
31
+ }
@@ -0,0 +1,12 @@
1
+ import sys
2
+ from pathlib import Path
3
+
4
+
5
+ ONBOARD_DIR = Path(__file__).resolve().parent / "onboard"
6
+ sys.path.insert(0, str(ONBOARD_DIR))
7
+
8
+ from robot_runtime import main # noqa: E402
9
+
10
+
11
+ if __name__ == "__main__":
12
+ raise SystemExit(main())