Fold LEGACY into the generation folders
The LEGACY copies of HexapodRobot, Hexapod_NEW, Hexapod_Teensy and the old remote sketch were identical to the imported repos and are removed. The old Nextion design moves to 2019-teensy-nrf24/remote-nextion/, the 2019 remote case files to 2019-teensy-nrf24/remote-case/. Paths in CLAUDE.md, READMEs, remote/ comments, sim/build.ps1, the Unity DLL message and .vscode/settings.json now point to the new places. robot/ is not touched (its CLAUDE.md asks to check with the owner first).
This commit is contained in:
1 parent
c666bc6039
commit
dfd4d34512
38 files changed
+37
-2413
No files matched your search
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"cmake.sourceDirectory": "D:/Claude/Hexapod/sim"
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/sim"
|
||||
}
|
||||
+22
-15
@@ -14,14 +14,21 @@ remote/ Teensy 4.1 firmware (PlatformIO env remote)
|
||||
shared/HexapodProtocol/ wire protocol, used by robot, remote and sim
|
||||
sim/ robot firmware -> hexapod_sim.dll (CMake + g++), headless smoke test
|
||||
Hexapod_Simulation_Unity/ Unity 6000.6 project that loads the DLL (Assets/HexapodSim/)
|
||||
LEGACY/ owner's older material for reference (remote/remote.HMI = old Nextion UI, 6 pages;
|
||||
remote/teensy/ = old remote sketch from https://mangavalk.com/Hexapod/remote.git @ 492dece;
|
||||
Hexapod_Teensy/ = old robot sketch: servo passthrough only, no IK - see "Old robot sketch" below;
|
||||
Hexapod_NEW/, HexapodRobot/ = older generations with their own IK, driving an external
|
||||
SSC-32-style servo controller - all three from https://mangavalk.com/Hexapod/Hexapod @ 7945005)
|
||||
scripts/ PlatformIO helper
|
||||
```
|
||||
|
||||
This folder is `2026-current/` inside the `hexapod-robot` repo. The older generations sit next to it
|
||||
(paths below are relative to this folder) and are the owner's reference material:
|
||||
|
||||
```
|
||||
../2019-teensy-nrf24/robot/ old robot sketch: servo passthrough only, no IK - see "Old robot sketch" below
|
||||
../2019-teensy-nrf24/remote/ old remote sketch
|
||||
../2019-teensy-nrf24/remote-nextion/ remote.HMI = old Nextion UI, 6 pages
|
||||
../2016-ssc32-processing-port/, older generations with their own IK, driving an external
|
||||
../2014-ik-core-task-queue/ SSC-32-style servo controller
|
||||
../README.md timeline of every generation since 2009
|
||||
```
|
||||
|
||||
PlatformIO, one `platformio.ini`, two environments:
|
||||
|
||||
| Env | Board | Sketch dir | Purpose |
|
||||
@@ -178,9 +185,8 @@ Remote stick-frame convention: logical X + = right, Y + = forward, twist +
|
||||
fit" model flipped the body as soon as it rolled (only one side
|
||||
counted as grounded); don't reintroduce it.
|
||||
- Robot forward = Unity −X, 1 Unity unit = 10 mm.
|
||||
- The Unity project was folded in from its own repo. Its history is in
|
||||
`D:\Claude\Hexapod_Simulation_Unity-history.bundle`. Its nested `.git`
|
||||
must be removed by the owner (deleting it was blocked for Claude).
|
||||
- The Unity project grew out of the 2018-2023 Unity simulation, which is in
|
||||
`../2018-unity-sim/` with its full history.
|
||||
|
||||
## Testing without the other board
|
||||
|
||||
@@ -294,7 +300,7 @@ Robot (`robot/README.md` has detail):
|
||||
push opposite to the commanded motion. The harness `z`/`c` keys were
|
||||
corrected to `z` = `yaw_rate` + (turn left). `sim_smoke` checks that
|
||||
+vx goes forward and +yaw_rate turns left.
|
||||
- **Old robot sketch (`LEGACY/Hexapod_Teensy/`)**: real hardware facts.
|
||||
- **Old robot sketch (`../2019-teensy-nrf24/robot/`)**: real hardware facts.
|
||||
It received 18 servo angles (0–180) over RF24Network (channel 90) from
|
||||
the old remote/Unity and wrote them with PWMServo. No IK, no gait.
|
||||
- **Board:** Teensy 3.6 (pins 36–39 and `SPI.setSCK(14)`, confirmed by
|
||||
@@ -322,15 +328,15 @@ Robot (`robot/README.md` has detail):
|
||||
- tibia servo = −tibia (right), 180 + tibia (left), so 90 = knee bent
|
||||
90°.
|
||||
- All of this is now in `Config.h` `SERVOS` (see "Servos" above).
|
||||
- **Older sketches (`LEGACY/Hexapod_NEW/`, `LEGACY/HexapodRobot/`, 2014–2016
|
||||
era)**: an earlier electronics generation. They did IK on the board and
|
||||
- **Older sketches (`../2016-ssc32-processing-port/`, `../2014-ik-core-task-queue/`,
|
||||
2014–2016 era)**: an earlier electronics generation. They did IK on the board and
|
||||
sent `#n Pxxxx … T0` text commands over `Serial1` to an external
|
||||
SSC-32-style servo controller (channels 0–9 and 16–24).
|
||||
- **Femur range:** it was already narrower there (600–2400 µs coxa/tibia,
|
||||
960–2100 µs femur over 0–180°), which corroborates the ≈6.7 µs/° femur
|
||||
in `SERVOS`.
|
||||
- **Links:** femur 10, tibia 15 (cm), with no coxa length in that IK.
|
||||
- **Hip layout comment in `Hexapod_NEW/HexapodClass.h`:** width 9.5 cm
|
||||
- **Hip layout comment in `../2016-ssc32-processing-port/HexapodClass.h`:** width 9.5 cm
|
||||
(front/rear) and 14 cm (middle), 10 cm front-to-middle-to-rear. The
|
||||
Unity model has 10 / 13 / 10. Whichever chassis is current, measure
|
||||
before trusting `LEG_MOUNT_*`.
|
||||
@@ -351,10 +357,10 @@ Remote (`remote/README.md` has detail):
|
||||
- `IMU_AXIS_FROM_CHIP` / `IMU_AXIS_SIGN` depend on how the MPU6050 is
|
||||
mounted in the handset.
|
||||
- The Nextion must have `bauds=115200` in Program.s, and the HMI must match
|
||||
`NEXTION.md`. The owner's old 6-page HMI is in `LEGACY/remote/remote.HMI`;
|
||||
`NEXTION.md`. The owner's old 6-page HMI is in `../2019-teensy-nrf24/remote-nextion/remote.HMI`;
|
||||
its component names aren't readable outside Nextion Editor. The compiled
|
||||
`.tft` is gitignored.
|
||||
- What the old remote sketch (`LEGACY/remote/teensy/`, last ran on a
|
||||
- What the old remote sketch (`../2019-teensy-nrf24/remote/`, last ran on a
|
||||
Teensy) tells us about the real hardware:
|
||||
- **Nextion on `Serial1` (pins 0/1)**, driven by the ITEAD Nextion
|
||||
library, whose `nexInit()` runs at 9600. `remote/Config.h` now uses
|
||||
@@ -394,7 +400,8 @@ Remote (`remote/README.md` has detail):
|
||||
first even then. Flag suspected robot bugs instead of fixing them. To
|
||||
try a robot fix, copy `robot/ shared/ sim/` to a scratch dir, patch the
|
||||
copy and run `sim_smoke` there.
|
||||
- `LEGACY/` is reference material from the owner. Don't modify it.
|
||||
- The older generations (`../20xx-*/`, `../original-frame/`) are reference
|
||||
material from the owner. Don't modify them.
|
||||
- Protocol changes go in `shared/HexapodProtocol/` only. Update the size
|
||||
`static_assert`, this file's contract table, and both READMEs.
|
||||
- Match the existing style: config constants at the top of `Config.h`
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace HexapodSim
|
||||
{
|
||||
if (!File.Exists(dllPath))
|
||||
throw new FileNotFoundException(
|
||||
"Simulation DLL not found. Build it first: run .\\sim\\build.ps1 from the repo root in PowerShell.",
|
||||
"Simulation DLL not found. Build it first: run .\\sim\\build.ps1 from the 2026-current folder in PowerShell.",
|
||||
dllPath);
|
||||
|
||||
var n = new HexapodSimNative();
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#ifndef HEX
|
||||
#define HEX
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "SerD.h"
|
||||
#include <QueueList.h>
|
||||
|
||||
// Angle to Pulse Length converter.
|
||||
#define smin0 600
|
||||
#define smin1 960
|
||||
#define smin2 600
|
||||
#define smin3 600
|
||||
#define smax0 2400
|
||||
#define smax1 2100
|
||||
#define smax2 2400
|
||||
#define smax3 2400
|
||||
|
||||
// Task Pipeline
|
||||
#define H_TASK 001
|
||||
#define H_IK 002
|
||||
#define H_IKER 003
|
||||
#define H_ATPC 004
|
||||
|
||||
// ProgramControl
|
||||
#define PC_EMPTY 101
|
||||
#define PC_NEEDDATA 102
|
||||
|
||||
// LAYOUT
|
||||
// _U_
|
||||
// 0==/ \==3
|
||||
// >***<
|
||||
// 1===|---|===4
|
||||
// >***<
|
||||
// 2==\___/==5
|
||||
|
||||
class Hexapod
|
||||
{
|
||||
private:
|
||||
// Task Pipeline.
|
||||
QueueList<int> TaskQueue;
|
||||
QueueList<int> Parameter;
|
||||
|
||||
// Program Control
|
||||
int PcCommand;
|
||||
|
||||
// Timing.
|
||||
int OldTime;
|
||||
int TimeBetweenNewPosition;
|
||||
|
||||
/* Servo Data
|
||||
# Including coordinate, Angle and Pulse Length.
|
||||
*/
|
||||
boolean DataReady;
|
||||
SerD ServoData[6];
|
||||
|
||||
// Inverse Kinemetics.
|
||||
float s;
|
||||
float l3;
|
||||
#define l2 15
|
||||
#define l1 10
|
||||
|
||||
void RL3 (int i)
|
||||
{
|
||||
float x = ServoData[i].x;
|
||||
float z = ServoData[i].z;
|
||||
|
||||
if ((x == 0) && (z == 0))
|
||||
l3 = 0;
|
||||
else l3 = hypot(z, x);
|
||||
|
||||
if (x < 0)
|
||||
l3 *= -1;
|
||||
}
|
||||
|
||||
float O1 (int i)
|
||||
{
|
||||
RL3(i);
|
||||
|
||||
float x = ServoData[i].x;
|
||||
float z = ServoData[i].z;
|
||||
float r;
|
||||
|
||||
if ((x != 0) & (z != 0)){
|
||||
double a = (z / x);
|
||||
return atan(a);
|
||||
}
|
||||
else
|
||||
return atan(0.0); // Math Error Protection.
|
||||
}
|
||||
|
||||
float T1 (int i)
|
||||
{
|
||||
float x = ServoData[i].x;
|
||||
float y = ServoData[i].y;
|
||||
float z = ServoData[i].z;
|
||||
float x2 = x * x;
|
||||
float y2 = y * y;
|
||||
float z2 = z * z;
|
||||
float l32 = l3 * l3;
|
||||
|
||||
s = sqrt(x2 + y2 + z2);
|
||||
|
||||
float t1 = 0;
|
||||
|
||||
float s2 = s * s;
|
||||
|
||||
if ((y == 0) && (l3 == 0))
|
||||
t1 = 0; // Math Error Protection.
|
||||
else
|
||||
t1 = (atan2(float(l3), float(y)));
|
||||
|
||||
float a = (l1 * l1) - (l2*l2) + s2;
|
||||
float b = 2 * l1 * s;
|
||||
float t2 = acos(a / b);
|
||||
|
||||
float ret = 0;
|
||||
|
||||
ret = t1 + abs(t2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float T3 ()
|
||||
{
|
||||
return (acos(((l1*l1) + (l2*l2) - (s*s)) / (2 * l1 * l2)));
|
||||
}
|
||||
|
||||
void setleg (int i)
|
||||
{
|
||||
if (i < 3)
|
||||
{
|
||||
float a = ((float)90 - degrees(O1(i)));
|
||||
float b = ((float)180 - degrees(T1(i)));
|
||||
float c = degrees(T3());
|
||||
|
||||
if ((a >= 0) & (a <= 180)
|
||||
& (b >= 0) & (b <= 180)
|
||||
& (c >= 0) & (c <= 180))
|
||||
{
|
||||
ServoData[i].o1 = a;
|
||||
ServoData[i].o2 = b;
|
||||
ServoData[i].o3 = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskQueue.push(H_IKER);
|
||||
Parameter.push(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float a = ((float)90 + degrees(O1(i)));
|
||||
float b = degrees(T1(i));
|
||||
float c = ((float)180 - degrees(T3()));
|
||||
|
||||
if ((a >= 0) & (a <= 180)
|
||||
& (b >= 0) & (b <= 180)
|
||||
& (c >= 0) & (c <= 180))
|
||||
{
|
||||
ServoData[i].o1 = a;
|
||||
ServoData[i].o2 = b;
|
||||
ServoData[i].o3 = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskQueue.push(H_IKER);
|
||||
Parameter.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IK()
|
||||
{
|
||||
for (int i=0; i<6; i++)
|
||||
setleg(i);
|
||||
}
|
||||
|
||||
// Angle to Pulse Length converter.
|
||||
|
||||
int ConverttoMS(int Position, int low, int high)
|
||||
{
|
||||
int tmp = ( Position * ( ( high - low ) / 180 ) );
|
||||
return low + tmp;
|
||||
}
|
||||
|
||||
void ConvertAngleToPulseLength()
|
||||
{
|
||||
for (int i=0; i<6; i++)
|
||||
{
|
||||
ServoData[i].t1 = ConverttoMS(ServoData[i].o1, smin0, smax0);
|
||||
ServoData[i].t2 = ConverttoMS(ServoData[i].o2, smin1, smax1);
|
||||
ServoData[i].t3 = ConverttoMS(ServoData[i].o3, smin2, smax2);
|
||||
}
|
||||
}
|
||||
|
||||
void ProgramControl( int Command )
|
||||
{
|
||||
// Drop task from queue
|
||||
TaskQueue.pop();
|
||||
|
||||
// Check Command.
|
||||
switch (Command)
|
||||
{
|
||||
case PC_EMPTY:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PC_NEEDDATA:
|
||||
{
|
||||
/*
|
||||
Queue = {
|
||||
Get Move
|
||||
Do IK
|
||||
Convert To MS
|
||||
Send }
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// Task Pipeline.
|
||||
void loop()
|
||||
{
|
||||
PcCommand = 0;
|
||||
do{
|
||||
/*
|
||||
Runmonitoing methods and
|
||||
Timingdependent methods.
|
||||
*/
|
||||
if (millis() >= (OldTime + TimeBetweenNewPosition))
|
||||
{
|
||||
OldTime = millis();
|
||||
}
|
||||
|
||||
//Add Task toqueue
|
||||
TaskQueue.push(H_TASK);
|
||||
|
||||
//task queue.
|
||||
|
||||
switch ( TaskQueue.peek() )
|
||||
{
|
||||
|
||||
case H_TASK:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case H_IK: // Do InverseKinemetics.
|
||||
{
|
||||
IK();
|
||||
break;
|
||||
}
|
||||
|
||||
case H_IKER: // Inverse Kinemetics Error.
|
||||
{
|
||||
while ( !Parameter.isEmpty() )
|
||||
{
|
||||
// Go troughtparameters.
|
||||
/*
|
||||
# W
|
||||
# I
|
||||
# P
|
||||
*/
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case H_ATPC: // Angel to pulse length converter.
|
||||
{
|
||||
ConvertAngleToPulseLength();
|
||||
DataReady = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case H_SEND:
|
||||
{
|
||||
if (DataReady)
|
||||
{
|
||||
// Send
|
||||
DataReady = false;
|
||||
// Get New Move
|
||||
}
|
||||
else
|
||||
{
|
||||
PcCommand = PC_NEEDDATA;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: // TaskList was empty.
|
||||
{
|
||||
// Do something when there is no task.
|
||||
PcCommand = PC_EMPTY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Program Control.
|
||||
ProgramControl( PcCommand );
|
||||
} while (1);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// Version 1
|
||||
#include "Hexapod.h"
|
||||
#include <QueueList.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Hexapod hexapod;
|
||||
|
||||
void loop()
|
||||
{
|
||||
hexapod.loop();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#ifndef SerD_H
|
||||
#define SerD_H
|
||||
|
||||
class SerD
|
||||
{
|
||||
public:
|
||||
|
||||
// Coordinate
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
|
||||
// Angles
|
||||
int o1;
|
||||
int o2;
|
||||
int o3;
|
||||
|
||||
// Pulse Length.
|
||||
int t1;
|
||||
int t2;
|
||||
int t3;
|
||||
|
||||
//Input
|
||||
SerD& operator() (int X, int Y, int Z)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SerD& operator= (SerD& R)
|
||||
{
|
||||
x = R.x;
|
||||
y = R.y;
|
||||
z = R.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#ifndef CustomTimer_H
|
||||
#define CustomTimer_H
|
||||
|
||||
class CustomTimer
|
||||
{
|
||||
int time;
|
||||
boolean start;
|
||||
public: CustomTimer()
|
||||
{
|
||||
start=false;
|
||||
}
|
||||
public: boolean Delay(int delay)
|
||||
{
|
||||
if (!start)
|
||||
{
|
||||
time = millis();
|
||||
start = true;
|
||||
}
|
||||
if (millis() - time >= delay)
|
||||
{
|
||||
start = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#ifndef Foot_H
|
||||
#define Foot_H
|
||||
|
||||
#include "Vector.h";
|
||||
#include "Global.h"
|
||||
|
||||
const double pi = 3.14159265359;
|
||||
|
||||
class Foot
|
||||
{
|
||||
public:
|
||||
float TranslateX, TranslateY, TranslateZ;
|
||||
boolean Invert;
|
||||
|
||||
void SetFootCoordinates(Vector P)
|
||||
{
|
||||
Xi = P.x;
|
||||
Yi = P.y;
|
||||
Zi = P.z;
|
||||
}
|
||||
|
||||
// ?used to put in position from body?
|
||||
void Translate(int x, int y, int z)
|
||||
{
|
||||
TranslateX = x;
|
||||
TranslateY = y;
|
||||
TranslateZ = z;
|
||||
}
|
||||
|
||||
void Translate(Vector i)
|
||||
{
|
||||
TranslateX = i.x;
|
||||
TranslateY = i.y;
|
||||
TranslateZ = i.z;
|
||||
}
|
||||
|
||||
// Inverse Kinemetics Region
|
||||
double l3, s, O1, O2, O3, X2, Y2, Z2;
|
||||
double l1, l2;
|
||||
double Xi, Yi, Zi;
|
||||
double X, Y, Z;
|
||||
boolean error;
|
||||
|
||||
void RotateX()
|
||||
{
|
||||
Y = Y * cos(radians(rotationX)) - Z * sin(radians(rotationX));
|
||||
Z = Y * sin(radians(rotationX)) + Z * cos(radians(rotationX));
|
||||
}
|
||||
|
||||
void RotateY()
|
||||
{
|
||||
Z = Z * cos(radians(rotationY)) - X * sin(radians(rotationY));
|
||||
X = Z * sin(radians(rotationY)) + X * cos(radians(rotationY));
|
||||
}
|
||||
|
||||
void RotateZ()
|
||||
{
|
||||
X = X * cos(radians(rotationZ)) - Y * sin(radians(rotationZ));
|
||||
Y = X * sin(radians(rotationZ)) + Y * cos(radians(rotationZ));
|
||||
}
|
||||
|
||||
void RL3 ()
|
||||
{
|
||||
double x = X;
|
||||
double z = Z;
|
||||
|
||||
if ((x == 0) && (z == 0))
|
||||
l3 = 0;
|
||||
else l3 = sqrt((float)(x * x + z * z));
|
||||
|
||||
if (x < 0)
|
||||
l3 = l3 * -1;
|
||||
}
|
||||
|
||||
float FO1 ()
|
||||
{
|
||||
RL3();
|
||||
|
||||
double x = X;
|
||||
double z = Z;
|
||||
double r;
|
||||
|
||||
if ((x != 0) & (z != 0)) {
|
||||
double a = (z / x);
|
||||
return atan((float)(a));
|
||||
}
|
||||
else
|
||||
return atan(0.0); // Math Error Protection.
|
||||
}
|
||||
|
||||
float T1 ()
|
||||
{
|
||||
float x = X;
|
||||
float y = Y;
|
||||
float z = Z;
|
||||
float x2 = x * x;
|
||||
float y2 = y * y;
|
||||
float z2 = z * z;
|
||||
float l32 = l3 * l3;
|
||||
|
||||
s = sqrt((float)(x2 + y2 + z2));
|
||||
|
||||
float t1 = 0;
|
||||
|
||||
float s2 = s * s;
|
||||
|
||||
if ((y == 0) && (l3 == 0))
|
||||
t1 = 0; // Math Error Protection.
|
||||
else
|
||||
t1 = (atan2((float)(l3), (float)(y)));
|
||||
|
||||
float a = (l1 * l1) - (l2 * l2) + s2;
|
||||
float b = 2 * l1 * s;
|
||||
float t2 = acos(a / b);
|
||||
|
||||
float ret = 0;
|
||||
|
||||
ret = t1 + abs(t2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float T3 ()
|
||||
{
|
||||
return (acos((float)(((l1 * l1) + (l2 * l2) - (s * s)) / (2 * l1 * l2))));
|
||||
}
|
||||
|
||||
void setleg()
|
||||
{
|
||||
setleg(Invert);
|
||||
}
|
||||
|
||||
void setleg(boolean Side)
|
||||
{
|
||||
l1 = 10;
|
||||
l2 = 15;
|
||||
|
||||
X = Xi;
|
||||
Y = Yi;
|
||||
Z = Zi;
|
||||
|
||||
// Rotation from body point
|
||||
if (Invert)
|
||||
{ // Right
|
||||
X = (-1 * X) + TranslateX;
|
||||
Z = (-1 * Z) + TranslateZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
X = Xi + TranslateX;
|
||||
Z = (-1 * Z) + TranslateZ;
|
||||
}
|
||||
|
||||
RotateY();
|
||||
RotateX();
|
||||
RotateZ();
|
||||
|
||||
// Remove gaits
|
||||
if (Invert)
|
||||
{ // Right
|
||||
X = -1 * (X - TranslateX);
|
||||
Z = -1 * (Z - TranslateZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
X -= TranslateX;
|
||||
Z = -1 * (Z - TranslateZ);
|
||||
}
|
||||
|
||||
if (Invert)
|
||||
{ // right
|
||||
double a = (90 - degrees(FO1()));
|
||||
double b = (180 - degrees(T1()));
|
||||
double c = degrees(T3());
|
||||
|
||||
/*if ((a >= 15) & (a <= 165)
|
||||
& (b >= 15) & (b <= 165)
|
||||
& (c >= 15) & (c <= 165))
|
||||
{*/
|
||||
error = false;
|
||||
|
||||
O1 = a;
|
||||
O2 = b;
|
||||
O3 = c;
|
||||
|
||||
double d = sin((float)(b * (pi / 180)));
|
||||
if ( d != 0 )
|
||||
X2 = d * l1;
|
||||
else
|
||||
X2 = 0;
|
||||
|
||||
d = cos((float)(b * (pi / 180)));
|
||||
if ( d != 0 )
|
||||
Y2 = d * l1;
|
||||
else
|
||||
Y2 = 0;
|
||||
|
||||
d = sin((float)((a - 90) * (pi / 180)));
|
||||
if ( d != 0 )
|
||||
Z2 = d * abs((float)(X2));
|
||||
else
|
||||
Z2 = 0;
|
||||
/*}
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
double a = (90 - degrees((float)(FO1())));
|
||||
double b = degrees((float)(T1()));
|
||||
double c = 180 - degrees((float)(T3()));
|
||||
|
||||
/*if ((a >= 15) & (a <= 165)
|
||||
& (b >= 15) & (b <= 165)
|
||||
& (c >= 15) & (c <= 165))
|
||||
{*/
|
||||
error = false;
|
||||
|
||||
O1 = a;
|
||||
O2 = b;
|
||||
O3 = c;
|
||||
|
||||
a = (90 - degrees((float)(FO1())));
|
||||
b = (180 - degrees((float)(T1())));
|
||||
c = degrees((float)(T3()));
|
||||
|
||||
double d = sin((float)(b * (pi / 180)));
|
||||
if ( d != 0 )
|
||||
X2 = d * l1;
|
||||
else
|
||||
X2 = 0;
|
||||
|
||||
d = sin((float)(b * (pi / 180)));
|
||||
if ( d != 0 )
|
||||
Y2 = d * l1;
|
||||
else
|
||||
Y2 = 0;
|
||||
|
||||
d = sin((float)((a - 90) * (pi / 180)));
|
||||
if ( d != 0 )
|
||||
Z2 = d * abs((float)(X2));
|
||||
else
|
||||
Z2 = 0;
|
||||
/*}
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
Serial.println("ERROR");
|
||||
}*/
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#ifndef Global_H
|
||||
#define Global_H
|
||||
|
||||
float rotationX = 0;
|
||||
float rotationY = 0;
|
||||
float rotationZ = 0;
|
||||
|
||||
CustomTimer timerAnimation = CustomTimer();
|
||||
CustomTimer TimerFPS_SERVO = CustomTimer();
|
||||
|
||||
const int FPS = 30;
|
||||
int FPS_SERVO = 30;
|
||||
|
||||
float counterRotation = 0;
|
||||
int counterXRotation = 0;
|
||||
int counterYRotation = 0;
|
||||
int counterZRotation = 0;
|
||||
|
||||
Vector *walk1 = new Vector[8];
|
||||
|
||||
float robotHeigth = 12;
|
||||
|
||||
int rotationRange = 8;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#ifndef Hexapod_H
|
||||
#define Hexapod_H
|
||||
|
||||
#include "FootClass.h";
|
||||
#include "Vector.h";
|
||||
#include "CustomTimer.h";
|
||||
#include "Global.h"
|
||||
#include <Streaming.h>
|
||||
|
||||
Foot foot1 = Foot();
|
||||
Foot foot2 = Foot();
|
||||
Foot foot3 = Foot();
|
||||
Foot foot4 = Foot();
|
||||
Foot foot5 = Foot();
|
||||
Foot foot6 = Foot();
|
||||
|
||||
// Spaces from body to feet
|
||||
// 9.5
|
||||
// 14
|
||||
// 9.5
|
||||
|
||||
// 10
|
||||
// 10
|
||||
|
||||
// LAYOUT HARDWARE
|
||||
// _U_
|
||||
// 1==/ \==4
|
||||
// >***<
|
||||
// 2===|---|===5
|
||||
// >***<
|
||||
// 3==\___/==6
|
||||
|
||||
// LAYOUT SOFTWARE
|
||||
// _U_
|
||||
// 1==/ \==6
|
||||
// >***<
|
||||
// 2===|---|===5
|
||||
// >***<
|
||||
// 3==\___/==4
|
||||
|
||||
Vector point1 = Vector(4.75, 0, 10);
|
||||
Vector point2 = Vector(7, 0, 0);
|
||||
Vector point3 = Vector(4.75, 0, -10);
|
||||
Vector point4 = Vector(-4.75, 0, -10);
|
||||
Vector point5 = Vector(-7, 0, 0);
|
||||
Vector point6 = Vector(-4.75, 0, 10);
|
||||
|
||||
Vector fpoint1 = Vector(10, 5, 0);
|
||||
Vector fpoint2 = Vector(10, 5, 0); // y negative is down from body.
|
||||
Vector fpoint3 = Vector(10, 5, 0);
|
||||
Vector fpoint4 = Vector(10, 5, 0);
|
||||
Vector fpoint5 = Vector(10, 5, 0);
|
||||
Vector fpoint6 = Vector(10, 5, 0);
|
||||
|
||||
Vector* standup = new Vector[2];
|
||||
|
||||
// Animation new
|
||||
int animationSpeed = 20;
|
||||
|
||||
int ConverttoMS(double Position, int low, int high, int _min = 15, int _max = 165, int correction = 0)
|
||||
{
|
||||
//Position += 90;
|
||||
|
||||
if (Position < _min | Position > _max)
|
||||
{
|
||||
Position = 90;
|
||||
Serial.println("ERROR");
|
||||
}
|
||||
|
||||
int tmp = ( Position * ( ( high - low ) / 180 ) );
|
||||
|
||||
//Serial1.println(Position);
|
||||
|
||||
return low + tmp + correction;
|
||||
}
|
||||
|
||||
void mSend(Foot f1, Foot f2, Foot f3, Foot f4, Foot f5, Foot f6)
|
||||
{
|
||||
int smin0 = 600;
|
||||
int smin1 = 960;
|
||||
int smin2 = 600;
|
||||
int smin3 = 600;
|
||||
int smax0 = 2400;
|
||||
int smax1 = 2100;
|
||||
int smax2 = 2400;
|
||||
int smax3 = 2400;
|
||||
|
||||
Serial1.print(" #");
|
||||
Serial1.print(0);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f4.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(1);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f4.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(2);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f4.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(3);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f5.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(4);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f5.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(5);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f5.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(6);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f6.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(7);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f6.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(8);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f6.O3, smin2, smax2));
|
||||
|
||||
Serial1.print(" #");
|
||||
Serial1.print(9);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(90, smin3, smax3));
|
||||
|
||||
Serial1.print(" #");
|
||||
Serial1.print(16);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(17);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(18);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(19);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f2.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(20);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f2.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(21);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f2.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(22);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f3.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(23);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f3.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(24);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f3.O3, smin2, smax2));
|
||||
|
||||
Serial1.print(" T");
|
||||
Serial1.println(0);
|
||||
|
||||
|
||||
|
||||
/*Serial << " #";
|
||||
Serial << 0;
|
||||
Serial << " P";
|
||||
Serial << f4.O1;
|
||||
Serial << " #";
|
||||
Serial << 1;
|
||||
Serial << " P";
|
||||
Serial << f4.O2;
|
||||
Serial << " #";
|
||||
Serial << 2;
|
||||
Serial << " P";
|
||||
Serial << f4.O3;
|
||||
Serial << " #";
|
||||
Serial << 3;
|
||||
Serial << " P";
|
||||
Serial << f5.O1;
|
||||
Serial << " #";
|
||||
Serial << 4;
|
||||
Serial << " P";
|
||||
Serial << f5.O2;
|
||||
Serial << " #";
|
||||
Serial << 5;
|
||||
Serial << " P";
|
||||
Serial << f5.O3;
|
||||
Serial << " #";
|
||||
Serial << 6;
|
||||
Serial << " P";
|
||||
Serial << f6.O1;
|
||||
Serial << " #";
|
||||
Serial << 7;
|
||||
Serial << " P";
|
||||
Serial << f6.O2;
|
||||
Serial << " #";
|
||||
Serial << 8;
|
||||
Serial << " P";
|
||||
Serial << f6.O3;
|
||||
|
||||
Serial << " #";
|
||||
Serial << 16;
|
||||
Serial << " P";
|
||||
Serial << f1.O1;
|
||||
Serial << " #";
|
||||
Serial << 17;
|
||||
Serial << " P";
|
||||
Serial << f1.O2;
|
||||
Serial << " #";
|
||||
Serial << 18;
|
||||
Serial << " P";
|
||||
Serial << f1.O3;
|
||||
Serial << " #";
|
||||
Serial << 19;
|
||||
Serial << " P";
|
||||
Serial << f2.O1;
|
||||
Serial << " #";
|
||||
Serial << 20;
|
||||
Serial << " P";
|
||||
Serial << f2.O2;
|
||||
Serial << " #";
|
||||
Serial << 21;
|
||||
Serial << " P";
|
||||
Serial << f2.O3;
|
||||
Serial << " #";
|
||||
Serial << 22;
|
||||
Serial << " P";
|
||||
Serial << f3.O1;
|
||||
Serial << " #";
|
||||
Serial << 23;
|
||||
Serial << " P";
|
||||
Serial << f3.O2;
|
||||
Serial << " #";
|
||||
Serial << 24;
|
||||
Serial << " P";
|
||||
Serial << f3.O3;
|
||||
|
||||
Serial << " T";
|
||||
Serial << 0 << "\n\r";*/
|
||||
}
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void DrawFeet()
|
||||
{
|
||||
if (TimerFPS_SERVO.Delay(1000 / FPS_SERVO))
|
||||
{
|
||||
foot1.Translate(point1);
|
||||
foot1.SetFootCoordinates(fpoint1);
|
||||
foot1.Invert = true;
|
||||
foot1.setleg();
|
||||
|
||||
foot1.Translate(point2);
|
||||
foot2.SetFootCoordinates(fpoint2);
|
||||
foot2.Invert = true;
|
||||
foot2.setleg();
|
||||
|
||||
foot1.Translate(point3);
|
||||
foot3.SetFootCoordinates(fpoint3);
|
||||
foot3.Invert = true;
|
||||
foot3.setleg();
|
||||
|
||||
foot1.Translate(point4);
|
||||
foot4.SetFootCoordinates(fpoint4);
|
||||
foot4.Invert = false;
|
||||
foot4.setleg();
|
||||
|
||||
foot1.Translate(point5);
|
||||
foot5.SetFootCoordinates(fpoint5);
|
||||
foot5.Invert = false;
|
||||
foot5.setleg();
|
||||
|
||||
foot1.Translate(point6);
|
||||
foot6.SetFootCoordinates(fpoint6);
|
||||
foot6.Invert = false;
|
||||
foot6.setleg();
|
||||
|
||||
mSend(foot1, foot2, foot3, foot4, foot5, foot6);
|
||||
}
|
||||
}
|
||||
|
||||
/*void RobotWalk()
|
||||
{
|
||||
if (robotStanding)
|
||||
{
|
||||
//animationRepeat = true;
|
||||
animationSpeed = 20;
|
||||
|
||||
if (!animationRepeatComplete)
|
||||
if (timerAnimation.Delay(animationSpeed))
|
||||
animationSubStep++;
|
||||
|
||||
Serial1.println("robot walk animation");
|
||||
|
||||
foot1.SetFootCoordinates(Animation(walk1, 8, 0)); // BULLSHIT BUG
|
||||
foot1.SetFootCoordinates(Animation(walk1, 8, 0));
|
||||
foot2.SetFootCoordinates(Animation(walk1, 8, 4));
|
||||
foot3.SetFootCoordinates(Animation(walk1, 8, 0));//
|
||||
foot4.SetFootCoordinates(Animation(walk1, 8, 4));//
|
||||
foot5.SetFootCoordinates(Animation(walk1, 8, 0));
|
||||
foot6.SetFootCoordinates(Animation(walk1, 8, 4));
|
||||
}
|
||||
}*/
|
||||
|
||||
float _animationProgress = 0;
|
||||
bool rotation = false;
|
||||
|
||||
void RobotStandup()
|
||||
{
|
||||
standup[0] = Vector(10, 5, 0);
|
||||
standup[1] = Vector(10, 15, 0);
|
||||
|
||||
if (timerAnimation.Delay(1000 / FPS))
|
||||
{
|
||||
Serial.println("robot standup animation");
|
||||
|
||||
fpoint1.Lerp(standup[0], standup[1], _animationProgress);
|
||||
fpoint2.Lerp(standup[0], standup[1], _animationProgress);
|
||||
fpoint3.Lerp(standup[0], standup[1], _animationProgress);
|
||||
fpoint4.Lerp(standup[0], standup[1], _animationProgress);
|
||||
fpoint5.Lerp(standup[0], standup[1], _animationProgress);
|
||||
fpoint6.Lerp(standup[0], standup[1], _animationProgress);
|
||||
|
||||
Serial.println(point1.Print());
|
||||
|
||||
int _speed = 2;
|
||||
|
||||
_animationProgress = _animationProgress < 1.0f ? (_animationProgress + (1.0f / (FPS * _speed))) : 1.0f;
|
||||
|
||||
/*if (_animationProgress == 1)
|
||||
{
|
||||
int uhh = (millis() / 100) % 100;
|
||||
if (rotation == true)
|
||||
{
|
||||
Serial.println("rotate up");
|
||||
rotationZ = map((millis() / 100) % 100, 0, 99, -25, 25);
|
||||
if (uhh >= 99)
|
||||
{
|
||||
rotation = true;
|
||||
uhh++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("rotate upside down");
|
||||
rotationZ = map((millis() / 100) % 100, 0, 99, 25, -25);
|
||||
if (uhh >= 99)
|
||||
{
|
||||
rotation = false;
|
||||
uhh++;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBody()
|
||||
{
|
||||
RobotStandup();
|
||||
|
||||
//RobotWalk();
|
||||
|
||||
DrawFeet();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "CustomTimer.h"
|
||||
#include "HexapodClass.h"
|
||||
#include "Vector.h"
|
||||
#include "Global.h"
|
||||
|
||||
//#include <avr/wdt.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
//wdt_enable(WDTO_1S);
|
||||
|
||||
walk1[0] = Vector(12, robotHeigth, 2);
|
||||
walk1[1] = Vector(12, robotHeigth, 0);
|
||||
walk1[2] = Vector(12, robotHeigth, -2);
|
||||
walk1[3] = Vector(12, robotHeigth, -2);
|
||||
walk1[4] = Vector(12, robotHeigth - 10, -2);
|
||||
walk1[5] = Vector(12, robotHeigth - 10, 0);
|
||||
walk1[6] = Vector(12, robotHeigth - 10, 2);
|
||||
walk1[7] = Vector(12, robotHeigth, 2);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial1.begin(115200);
|
||||
|
||||
Serial.println("");
|
||||
Serial.println(" ____ ____ ___ ");
|
||||
Serial.println("/\\ _`\\ __ /\\ _`\\ /\\_ \\ ");
|
||||
Serial.println("\\ \\ \\L\\_\\/\\_\\ _ __ __\\ \\ \\L\\_\\//\\ \\ __ __ ");
|
||||
Serial.println(" \\ \\ _\\/\\/\\ \\/\\`'__\\/'__`\\ \\ _\\/ \\ \\ \\ /\\ \\/\\ \\ ");
|
||||
Serial.println(" \\ \\ \\/ \\ \\ \\ \\ \\//\\ __/\\ \\ \\/ \\_\\ \\_\\ \\ \\_\\ \\ ");
|
||||
Serial.println(" \\ \\_\\ \\ \\_\\ \\_\\\\ \\____\\\\ \\_\\ /\\____\\\\/`____ \\ ");
|
||||
Serial.println(" \\/_/ \\/_/\\/_/ \\/____/ \\/_/ \\/____/ `/___/> \\");
|
||||
Serial.println(" /\\___/");
|
||||
Serial.println(" \\/__/ ");
|
||||
Serial.println("");
|
||||
Serial.println("Version 3.0");
|
||||
delay(800);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// the program is alive...for now.
|
||||
//wdt_reset();
|
||||
|
||||
// Rotation calculation, please use transformation matrixes instead.
|
||||
//rotationX = ( counterXRotation % (rotationRange * 4) < (rotationRange * 2) ? -rotationRange + counterXRotation % (rotationRange * 2) : rotationRange + (-1 * (counterXRotation % (rotationRange * 2))) );
|
||||
//rotationY = ( counterYRotation % (rotationRange * 4) < (rotationRange * 2) ? -rotationRange + counterYRotation % (rotationRange * 2) : rotationRange + (-1 * (counterYRotation % (rotationRange * 2))) );
|
||||
//rotationZ = ( counterZRotation % (rotationRange * 4) < (rotationRange * 2) ? -rotationRange + counterZRotation % (rotationRange * 2) : rotationRange + (-1 * (counterZRotation % (rotationRange * 2))) );
|
||||
|
||||
DrawBody();
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
//#ifndef Servo_H
|
||||
//#define Servo_H
|
||||
|
||||
/*#include "FootClass.h";
|
||||
|
||||
int ConverttoMS(int Position, int low, int high)
|
||||
{
|
||||
int tmp = ( Position * ( ( high - low ) / 180 ) );
|
||||
return low + tmp;
|
||||
}
|
||||
|
||||
void mSend(Foot f1, Foot f2, Foot f3, Foot f4, Foot f5, Foot f6)
|
||||
{
|
||||
int smin0 = 600;
|
||||
int smin1 = 960;
|
||||
int smin2 = 600;
|
||||
int smin3 = 600;
|
||||
int smax0 = 2400;
|
||||
int smax1 = 2100;
|
||||
int smax2 = 2400;
|
||||
int smax3 = 2400;
|
||||
|
||||
Serial1.print(" #");
|
||||
Serial1.print(0);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(1);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(2);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(4);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(5);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(6);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(7);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(8);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(9);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O3, smin2, smax2));
|
||||
|
||||
Serial1.print(" #");
|
||||
Serial1.print(16);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(17);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(18);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(19);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(20);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(21);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O3, smin2, smax2));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(22);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O1, smin0, smax0));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(23);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O2, smin1, smax1));
|
||||
Serial1.print(" #");
|
||||
Serial1.print(24);
|
||||
Serial1.print(" P");
|
||||
Serial1.print(ConverttoMS(f1.O3, smin2, smax2));
|
||||
|
||||
Serial1.print(" T");
|
||||
Serial1.println(0);
|
||||
}*/
|
||||
|
||||
//#endif
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
// Version 1
|
||||
|
||||
#ifndef Servo_H
|
||||
#define Servo_H
|
||||
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
float x, y, z;
|
||||
Vector(float X, float Y, float Z)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
}
|
||||
void Init(float X, float Y, float Z)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
z = Z;
|
||||
}
|
||||
Vector()
|
||||
{
|
||||
|
||||
}
|
||||
Vector Lerp(Vector start, Vector end, float percent)
|
||||
{
|
||||
Vector _new = (start + ((end - start) * percent));
|
||||
x = _new.x;
|
||||
y = _new.y;
|
||||
z = _new.z;
|
||||
return _new;
|
||||
}
|
||||
Vector operator + (const Vector other)
|
||||
{
|
||||
Vector _new = Vector();
|
||||
_new.x = x + other.x;
|
||||
_new.y = y + other.y;
|
||||
_new.z = z + other.z;
|
||||
|
||||
return _new;
|
||||
}
|
||||
Vector operator - (const Vector other)
|
||||
{
|
||||
Vector _new = Vector();
|
||||
_new.x = x - other.x;
|
||||
_new.y = y - other.y;
|
||||
_new.z = z - other.z;
|
||||
|
||||
return _new;
|
||||
}
|
||||
Vector operator * (const float other)
|
||||
{
|
||||
Vector _new = Vector(x * other, y * other, z * other);
|
||||
|
||||
return _new;
|
||||
}
|
||||
String Print()
|
||||
{
|
||||
return String(x) + " " + String(y) + " " + String(z);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
#include "Nrf.h"
|
||||
#include <Wire.h>
|
||||
#include <MPU6050_tockn.h>
|
||||
#include "PWMServo.h"
|
||||
#include "config.h"
|
||||
|
||||
PWMServo servos[18];
|
||||
|
||||
MPU6050 mpu (Wire);
|
||||
|
||||
dataStruct2 data;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial1.begin(115200);
|
||||
// while (!Serial) ; // wait for arduino serial monitor
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
servos[i].attach(pins[i], servoMin[i] + servoCallibration[i],
|
||||
servoMax[i] + servoCallibration[i]); // 900-2100 for high torque servos
|
||||
// while (true)
|
||||
// {
|
||||
for (int i = 0; i < 18; i++)
|
||||
servos[i].write(90 + servoOffset[i]);
|
||||
// }
|
||||
|
||||
|
||||
Serial.println("Starting mpu6050");
|
||||
|
||||
// // Initialization
|
||||
// Wire.begin();
|
||||
// mpu.begin();
|
||||
//
|
||||
// mpu.calcGyroOffsets(true, 300, 1000);
|
||||
//
|
||||
// // Calibration
|
||||
// Serial.println("=====================================");
|
||||
// Serial.println("Starting calibration...");
|
||||
// mpu.calcGyroOffsets();
|
||||
// Serial.println("Calibration complete!");
|
||||
|
||||
Serial.println("Starting nrf");
|
||||
NrfInit();
|
||||
}
|
||||
|
||||
void STOP()
|
||||
{
|
||||
for (int i = 0; i < 18; i++)
|
||||
pinMode(pins[i], INPUT);
|
||||
while (true)
|
||||
{}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
void loop()
|
||||
{
|
||||
network.update();
|
||||
|
||||
if (false)
|
||||
{
|
||||
mpu.update();
|
||||
Serial.print("AngX = ");
|
||||
Serial.print(mpu.getAngleX());
|
||||
Serial.print(" / AngY = ");
|
||||
Serial.print(mpu.getAngleY());
|
||||
Serial.print(" / AngZ = ");
|
||||
Serial.println(mpu.getAngleZ());
|
||||
}
|
||||
|
||||
// Serial.print(" / AngX = ");
|
||||
// Serial.print(mpu.getGyroAngleX());
|
||||
// Serial.print(" / AngY = ");
|
||||
// Serial.print(mpu.getGyroAngleY());
|
||||
// Serial.print(" / AngZ = ");
|
||||
// Serial.println(mpu.getGyroAngleZ());
|
||||
|
||||
data = NrfGetData(data, true);
|
||||
|
||||
// if (data.STOP)
|
||||
// STOP();
|
||||
|
||||
// test
|
||||
// data.servoPositions[0] = data.servoPositions[0] + 0.1f;
|
||||
// data = NrfSendData(data, false);
|
||||
|
||||
if (data.remotePasstroughControl == true)
|
||||
for (int i = 0; i < 18; i++)
|
||||
servos[i].write(data.servoPositions[i] + servoOffset[i]);
|
||||
|
||||
delay(20);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
#include <RF24Network.h>
|
||||
#include "TransferDataStructure.h"
|
||||
|
||||
// Nrf24 settings
|
||||
RF24 radio(39, 15); // CE, CSN
|
||||
RF24Network network(radio);
|
||||
|
||||
const uint16_t this_node = 01; // Address of our node in Octal format
|
||||
const uint16_t other_node = 00; // Address of the other node in Octal format
|
||||
|
||||
void NrfInit()
|
||||
{
|
||||
SPI.setSCK(14);
|
||||
SPI.setMOSI(11);
|
||||
SPI.setMISO(12);
|
||||
|
||||
SPI.begin();
|
||||
radio.begin();
|
||||
network.begin(/*channel*/ 90, /*node address*/ this_node);
|
||||
|
||||
// Set the PA Level low to prevent power supply related issues since this is a
|
||||
// getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
|
||||
radio.setPALevel(RF24_PA_LOW);
|
||||
}
|
||||
|
||||
dataStruct2 NrfGetData(dataStruct2 data, bool debug = false)
|
||||
{
|
||||
// network.update();
|
||||
int timeout = millis() + 100;
|
||||
while ( network.available() && timeout > millis() )
|
||||
{
|
||||
RF24NetworkHeader header;
|
||||
network.read(header, &data, sizeof(data));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Serial.print("Received packet ");
|
||||
Serial.println(data.servoPositions[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
dataStruct2 NrfSendData(dataStruct2 data, bool debug = false)
|
||||
{
|
||||
// network.update();
|
||||
|
||||
if (debug)
|
||||
Serial.print("Sending...");
|
||||
|
||||
RF24NetworkHeader header(/*to node*/ other_node);
|
||||
bool ok = network.write(header, &data, sizeof(data));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
if (ok)
|
||||
Serial.println("ok.");
|
||||
else
|
||||
Serial.println("failed.");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
#include "Arduino.h"
|
||||
#include "PWMServo.h"
|
||||
|
||||
/*
|
||||
PWMServo.cpp - Hardware Servo Timer Library
|
||||
http://arduiniana.org/libraries/pwmservo/
|
||||
Author: Jim Studt, jim@federated.com
|
||||
Copyright (c) 2007 David A. Mellis. All right reserved.
|
||||
renamed to PWMServo by Mikal Hart
|
||||
ported to other chips by Paul Stoffregen
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define NO_ANGLE (0xff)
|
||||
|
||||
#if defined(__AVR__)
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
uint8_t PWMServo::attachedA = 0;
|
||||
uint8_t PWMServo::attachedB = 0;
|
||||
#ifdef SERVO_PIN_C
|
||||
uint8_t PWMServo::attachedC = 0;
|
||||
#endif
|
||||
|
||||
void PWMServo::seizeTimer1()
|
||||
{
|
||||
uint8_t oldSREG = SREG;
|
||||
|
||||
cli();
|
||||
TCCR1A = _BV(WGM11); /* Fast PWM, ICR1 is top */
|
||||
TCCR1B = _BV(WGM13) | _BV(WGM12) /* Fast PWM, ICR1 is top */
|
||||
| _BV(CS11) /* div 8 clock prescaler */
|
||||
;
|
||||
OCR1A = 3000;
|
||||
OCR1B = 3000;
|
||||
ICR1 = clockCyclesPerMicrosecond() * (20000L / 8); // 20000 uS is a bit fast for the refresh, 20ms, but
|
||||
// it keeps us from overflowing ICR1 at 20MHz clocks
|
||||
// That "/8" at the end is the prescaler.
|
||||
#if defined(__AVR_ATmega8__)
|
||||
TIMSK &= ~(_BV(TICIE1) | _BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
|
||||
#else
|
||||
TIMSK1 &= ~(_BV(OCIE1A) | _BV(OCIE1B) | _BV(TOIE1) );
|
||||
#endif
|
||||
|
||||
SREG = oldSREG; // undo cli()
|
||||
}
|
||||
|
||||
void PWMServo::releaseTimer1() {}
|
||||
|
||||
PWMServo::PWMServo() : pin(0), angle(NO_ANGLE) {}
|
||||
|
||||
uint8_t PWMServo::attach(int pinArg, int min, int max)
|
||||
{
|
||||
#ifdef SERVO_PIN_C
|
||||
if (pinArg != SERVO_PIN_A && pinArg != SERVO_PIN_B && pinArg != SERVO_PIN_C) return 0;
|
||||
#else
|
||||
if (pinArg != SERVO_PIN_A && pinArg != SERVO_PIN_B) return 0;
|
||||
#endif
|
||||
|
||||
min16 = min / 16;
|
||||
max16 = max / 16;
|
||||
|
||||
pin = pinArg;
|
||||
angle = NO_ANGLE;
|
||||
digitalWrite(pin, LOW);
|
||||
pinMode(pin, OUTPUT);
|
||||
|
||||
#ifdef SERVO_PIN_C
|
||||
if (!attachedA && !attachedB && !attachedC) seizeTimer1();
|
||||
#else
|
||||
if (!attachedA && !attachedB) seizeTimer1();
|
||||
#endif
|
||||
|
||||
if (pin == SERVO_PIN_A) {
|
||||
attachedA = 1;
|
||||
TCCR1A = (TCCR1A & ~_BV(COM1A0)) | _BV(COM1A1);
|
||||
}
|
||||
|
||||
if (pin == SERVO_PIN_B) {
|
||||
attachedB = 1;
|
||||
TCCR1A = (TCCR1A & ~_BV(COM1B0)) | _BV(COM1B1);
|
||||
}
|
||||
|
||||
#ifdef SERVO_PIN_C
|
||||
if (pin == SERVO_PIN_C) {
|
||||
attachedC = 1;
|
||||
TCCR1A = (TCCR1A & ~_BV(COM1C0)) | _BV(COM1C1);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PWMServo::detach()
|
||||
{
|
||||
// muck with timer flags
|
||||
if (pin == SERVO_PIN_A) {
|
||||
attachedA = 0;
|
||||
TCCR1A = TCCR1A & ~_BV(COM1A0) & ~_BV(COM1A1);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
if (pin == SERVO_PIN_B) {
|
||||
attachedB = 0;
|
||||
TCCR1A = TCCR1A & ~_BV(COM1B0) & ~_BV(COM1B1);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
#ifdef SERVO_PIN_C
|
||||
if (pin == SERVO_PIN_C) {
|
||||
attachedC = 0;
|
||||
TCCR1A = TCCR1A & ~_BV(COM1C0) & ~_BV(COM1C1);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SERVO_PIN_C
|
||||
if (!attachedA && !attachedB && !attachedC) releaseTimer1();
|
||||
#else
|
||||
if (!attachedA && !attachedB) releaseTimer1();
|
||||
#endif
|
||||
}
|
||||
|
||||
void PWMServo::write(int angleArg)
|
||||
{
|
||||
uint16_t p;
|
||||
|
||||
if (angleArg < 0) angleArg = 0;
|
||||
if (angleArg > 180) angleArg = 180;
|
||||
angle = angleArg;
|
||||
|
||||
// bleh, have to use longs to prevent overflow, could be tricky if always a 16MHz clock, but not true
|
||||
// That 8L on the end is the TCNT1 prescaler, it will need to change if the clock's prescaler changes,
|
||||
// but then there will likely be an overflow problem, so it will have to be handled by a human.
|
||||
p = (min16 * 16L * clockCyclesPerMicrosecond() + (max16 - min16) * (16L * clockCyclesPerMicrosecond()) * angle / 180L) / 8L;
|
||||
if (pin == SERVO_PIN_A) OCR1A = p;
|
||||
if (pin == SERVO_PIN_B) OCR1B = p;
|
||||
#ifdef SERVO_PIN_C
|
||||
if (pin == SERVO_PIN_C) OCR1C = p;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t PWMServo::attached()
|
||||
{
|
||||
if (pin == SERVO_PIN_A && attachedA) return 1;
|
||||
if (pin == SERVO_PIN_B && attachedB) return 1;
|
||||
#ifdef SERVO_PIN_C
|
||||
if (pin == SERVO_PIN_C && attachedC) return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(__arm__) && defined(TEENSYDUINO)
|
||||
|
||||
uint32_t PWMServo::attachedpins[(NUM_DIGITAL_PINS + 31) / 32]; // 1 bit per digital pin
|
||||
|
||||
PWMServo::PWMServo() : pin(255), angle(NO_ANGLE) {}
|
||||
|
||||
uint8_t PWMServo::attach(int pinArg, int min, int max)
|
||||
{
|
||||
// Serial.printf("attach, pin=%d, min=%d, max=%d\n", pinArg, min, max);
|
||||
if (pinArg < 0 || pinArg >= NUM_DIGITAL_PINS) return 0;
|
||||
if (!digitalPinHasPWM(pinArg)) return 0;
|
||||
pin = pinArg;
|
||||
analogWriteFrequency(pin, 50);
|
||||
min16 = min >> 4;
|
||||
max16 = max >> 4;
|
||||
angle = NO_ANGLE;
|
||||
digitalWrite(pin, LOW);
|
||||
pinMode(pin, OUTPUT);
|
||||
attachedpins[pin >> 5] |= (1 << (pin & 31));
|
||||
// Serial.println("Succes!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PWMServo::write(float angleArg)
|
||||
{
|
||||
//Serial.printf("write, pin=%d, angle=%d\n", pin, angleArg);
|
||||
if (pin >= NUM_DIGITAL_PINS) return;
|
||||
if (angleArg < 0) angleArg = 0;
|
||||
if (angleArg > 180) angleArg = 180;
|
||||
angle = angleArg;
|
||||
|
||||
uint32_t us = (((max16 - min16) * 46603 * (uint8_t)angle) >> 11) + (min16 << 12); // us*256
|
||||
//uint32_t duty = (us * 3355) >> 22;
|
||||
|
||||
float usec = (float)((max16 - min16) << 4) * ((float)angle / 180.0f) + (float)(min16 << 4);
|
||||
uint32_t duty = (int)(usec / 20000.0f * 4096.0f);
|
||||
|
||||
if (false)
|
||||
Serial.printf("pin=%d, angle=%.2f, usec=%.2f, us=%.2f, duty=%d, min=%d, max=%d\n",
|
||||
pin, (float)angle, usec, (float)us / 256.0f, duty, min16 << 4, max16 << 4);
|
||||
|
||||
#if TEENSYDUINO >= 137
|
||||
noInterrupts();
|
||||
uint32_t oldres = analogWriteResolution(12);
|
||||
analogWrite(pin, duty);
|
||||
analogWriteResolution(oldres);
|
||||
interrupts();
|
||||
#else
|
||||
analogWriteResolution(12);
|
||||
analogWrite(pin, duty);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t PWMServo::attached()
|
||||
{
|
||||
if (pin >= NUM_DIGITAL_PINS) return 0;
|
||||
return (attachedpins[pin >> 5] & (1 << (pin & 31))) ? 1 : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,94 +0,0 @@
|
||||
#ifndef PWMServo_h
|
||||
#define PWMServo_h
|
||||
|
||||
/*
|
||||
PWMServo.h - Hardware Servo Timer Library
|
||||
http://arduiniana.org/libraries/pwmservo/
|
||||
Author: Jim Studt, jim@federated.com
|
||||
Copyright (c) 2007 David A. Mellis. All right reserved.
|
||||
renamed to PWMServo by Mikal Hart
|
||||
ported to other chips by Paul Stoffregen
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) // Arduino
|
||||
#define SERVO_PIN_A 9
|
||||
#define SERVO_PIN_B 10
|
||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // Arduino Mega
|
||||
#define SERVO_PIN_A 11
|
||||
#define SERVO_PIN_B 12
|
||||
#define SERVO_PIN_C 13
|
||||
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) // Sanguino
|
||||
#define SERVO_PIN_A 13
|
||||
#define SERVO_PIN_B 12
|
||||
#elif defined(__AVR_AT90USB162__) // Teensy 1.0
|
||||
#define SERVO_PIN_A 17
|
||||
#define SERVO_PIN_B 18
|
||||
#define SERVO_PIN_C 15
|
||||
#elif defined(__AVR_ATmega32U4__) // Teensy 2.0
|
||||
#define SERVO_PIN_A 14
|
||||
#define SERVO_PIN_B 15
|
||||
#define SERVO_PIN_C 4
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) // Teensy++
|
||||
#define SERVO_PIN_A 25
|
||||
#define SERVO_PIN_B 26
|
||||
#define SERVO_PIN_C 27
|
||||
#elif defined(__arm__) && defined(TEENSYDUINO)
|
||||
#define SERVO_PIN_A 9
|
||||
#define SERVO_PIN_B 10
|
||||
// all PWM pins supported, but names not defined here...
|
||||
// just use the actual PWM pin number with attach()
|
||||
#else
|
||||
#define SERVO_PIN_A 9
|
||||
#define SERVO_PIN_B 10
|
||||
#endif
|
||||
|
||||
class PWMServo
|
||||
{
|
||||
private:
|
||||
uint8_t pin;
|
||||
float angle; // in degrees
|
||||
uint8_t min16; // minimum pulse, 16uS units (default is 34)
|
||||
uint8_t max16; // maximum pulse, 16uS units, 0-4ms range (default is 150)
|
||||
#if defined(__AVR__)
|
||||
static void seizeTimer1();
|
||||
static void releaseTimer1();
|
||||
static uint8_t attachedA;
|
||||
static uint8_t attachedB;
|
||||
#ifdef SERVO_PIN_C
|
||||
static uint8_t attachedC;
|
||||
#endif
|
||||
#elif defined(__arm__) && defined(TEENSYDUINO)
|
||||
static uint32_t attachedpins[]; // 1 bit per digital pin
|
||||
#endif
|
||||
public:
|
||||
PWMServo();
|
||||
uint8_t attach(int pinArg) { return attach(pinArg, 544, 2400); }
|
||||
// pulse length for 0 degrees in microseconds, 544uS default
|
||||
// pulse length for 180 degrees in microseconds, 2400uS default
|
||||
uint8_t attach(int pinArg, int min, int max);
|
||||
// attach to a pin, sets pinMode, returns 0 on failure, won't
|
||||
// position the servo until a subsequent write() happens
|
||||
// Only works for 9 and 10.
|
||||
void detach();
|
||||
void write(float angleArg); // specify the angle in degrees, 0 to 180
|
||||
uint8_t read() { return angle; }
|
||||
uint8_t attached();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef dataStruct
|
||||
#define dataStruct
|
||||
|
||||
struct __attribute__((__packed__)) dataStruct2
|
||||
{
|
||||
bool STOP = false;
|
||||
|
||||
float walkSpeed = 10; //step size
|
||||
float walkSpeed2 = 0; //gate speed
|
||||
float walkRotation = 0 ;
|
||||
float walkDirection = 0;
|
||||
|
||||
float tranform[3] = {0, 0, 0};
|
||||
float tranform2[3] = {0, 0, 0};
|
||||
float rotation[3] = {0, 0, 0};
|
||||
|
||||
bool remotePasstroughControl = true;
|
||||
float servoPositions[18] = {
|
||||
90, 90, 90,
|
||||
90, 90, 90,
|
||||
90, 90, 90,
|
||||
|
||||
90, 90, 90,
|
||||
90, 90, 90,
|
||||
90, 90, 90
|
||||
};
|
||||
} dataStruct;
|
||||
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
byte pins[18] = {4, 3, 2,
|
||||
7, 6, 5,
|
||||
10, 9, 8,
|
||||
|
||||
23, 22, 21,
|
||||
20, 36, 37,
|
||||
17, 16, 38
|
||||
};
|
||||
|
||||
int servoMin[18] = {553, 840, 553,
|
||||
553, 840, 553,
|
||||
553, 840, 553,
|
||||
|
||||
553, 840, 553,
|
||||
553, 840, 553,
|
||||
553, 840, 553
|
||||
};
|
||||
|
||||
int servoMax[18] = {2425, 2050, 2425,
|
||||
2425, 2050, 2425,
|
||||
2425, 2050, 2425,
|
||||
|
||||
2425, 2050, 2425,
|
||||
2425, 2050, 2425,
|
||||
2425, 2050, 2425
|
||||
};
|
||||
|
||||
int servoCallibration[18] = {0, 100, 0,
|
||||
0, 100, -30,
|
||||
0, 80, -50,
|
||||
|
||||
-120, 0, 0,
|
||||
-10, 20, 0,
|
||||
0, 20, -80
|
||||
};
|
||||
|
||||
float servoOffset[18] = {0, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
|
||||
90, 0, 0,
|
||||
0, 0, 0,
|
||||
-90, 0, 0
|
||||
};
|
||||
Binary file not shown.
@@ -1,127 +0,0 @@
|
||||
#include <EEPROM.h>
|
||||
|
||||
// start reading from the first byte (address 0) of the EEPROM
|
||||
unsigned int address = 0;
|
||||
byte value;
|
||||
|
||||
// Joystick vars
|
||||
const int analogInPin = A0;
|
||||
|
||||
int sensorValue = 0;
|
||||
int outputValue = 0;
|
||||
|
||||
//volatile int center[6] = {0, 0, 0, 0, 0, 0};
|
||||
//volatile int minvalue[6] = {1000, 1000, 1000, 1000, 1000, 1000}; //ARDUINO
|
||||
//volatile int maxvalue[6] = {0, 0, 0, 0, 0, 0}; //ARDUINO
|
||||
int minvalue[6] = {1000, 1000, 1000, 1000, 1000, 1000}; //TEENSY
|
||||
int maxvalue[6] = {0, 0, 0, 0, 0, 0}; //TEENSY
|
||||
|
||||
void JoystickInit()
|
||||
{
|
||||
// Initialize joysticks first
|
||||
value = EEPROM.read(address);
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
address++;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
address += sizeof(int);
|
||||
EEPROM.get(address, minvalue[i]);
|
||||
address += sizeof(int);
|
||||
EEPROM.get(address, maxvalue[i]);
|
||||
// Serial.println(minvalue[i]);
|
||||
// Serial.println(maxvalue[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if eeprom empty
|
||||
delay(500);
|
||||
|
||||
// for (int i = 0; i < 6; i++)
|
||||
// {
|
||||
// center[i] = analogRead(analogInPin + i);
|
||||
// }
|
||||
|
||||
int time = 10000;
|
||||
while (millis() < time)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
sensorValue = analogRead(analogInPin + i);
|
||||
if (sensorValue > maxvalue[i]) {
|
||||
maxvalue[i] = sensorValue;
|
||||
}
|
||||
if (sensorValue < minvalue[i]) {
|
||||
minvalue[i] = sensorValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for (int i = 0; i < 6; i++)
|
||||
// {
|
||||
// minvalue[i] = center[i] - minvalue[i];
|
||||
// maxvalue[i] = (maxvalue[i] - center[i]);
|
||||
// }
|
||||
|
||||
// write callibration to eeprom
|
||||
address = 0;
|
||||
EEPROM.write(address, 1);
|
||||
|
||||
address++;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
address += sizeof(int);
|
||||
EEPROM.put(address, minvalue[i]);
|
||||
address += sizeof(int);
|
||||
EEPROM.put(address, maxvalue[i]);
|
||||
// Serial.println(minvalue[i]);
|
||||
// Serial.println(maxvalue[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct joyStickdataStruct {
|
||||
float value[6];
|
||||
} myJoyStickdataStruct;
|
||||
|
||||
joyStickdataStruct JoystickGet(bool debug = false)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
sensorValue = analogRead(analogInPin + i);
|
||||
|
||||
if (sensorValue > maxvalue[i])
|
||||
maxvalue[i] = sensorValue;
|
||||
if (sensorValue < minvalue[i])
|
||||
minvalue[i] = sensorValue;
|
||||
|
||||
outputValue = map(sensorValue, minvalue[i], maxvalue[i], 0, 255);
|
||||
outputValue = sensorValue > maxvalue[i] ? 255 : sensorValue < minvalue[i] ? 0 : outputValue;
|
||||
// if (sensorValue <= center[i])
|
||||
// {
|
||||
// outputValue = map(sensorValue, minvalue[i], center[i], 0, 127);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// outputValue = map(sensorValue, center[i], maxvalue[i], 128, 255);
|
||||
// }
|
||||
|
||||
myJoyStickdataStruct.value[i] = outputValue;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Serial.print(i);
|
||||
Serial.print("_");
|
||||
Serial.print(myJoyStickdataStruct.value[i]);
|
||||
if (i != 5)
|
||||
Serial.print(",");
|
||||
// Serial.print(" ");
|
||||
}
|
||||
}
|
||||
if (debug)
|
||||
Serial.println();
|
||||
|
||||
return myJoyStickdataStruct;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
#include <RF24Network.h>
|
||||
#include "TransferDataStructure.h"
|
||||
|
||||
// Nrf24 settings
|
||||
RF24 radio(9, 10); // CE, CSN
|
||||
RF24Network network(radio);
|
||||
|
||||
const uint16_t this_node = 00; // Address of our node in Octal format
|
||||
const uint16_t other_node = 01; // Address of the other node in Octal format
|
||||
|
||||
void NrfInit()
|
||||
{
|
||||
SPI.begin();
|
||||
radio.begin();
|
||||
network.begin(/*channel*/ 90, /*node address*/ this_node);
|
||||
|
||||
// Set the PA Level low to prevent power supply related issues since this is a
|
||||
// getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
|
||||
radio.setPALevel(RF24_PA_LOW);
|
||||
}
|
||||
|
||||
bool NrfSendData(dataStruct2 data, bool debug = false)
|
||||
//dataStruct2 NrfSendData(dataStruct2 data, bool debug = false)
|
||||
{
|
||||
// network.update();
|
||||
|
||||
if (debug)
|
||||
Serial.print("Sending...");
|
||||
|
||||
RF24NetworkHeader header(/*to node*/ other_node);
|
||||
bool ok = network.write(header, &data, sizeof(data));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
if (ok)
|
||||
Serial.println("ok.");
|
||||
else
|
||||
Serial.println("failed.");
|
||||
}
|
||||
|
||||
return ok;
|
||||
// return data;
|
||||
}
|
||||
|
||||
dataStruct2 NrfGetData(dataStruct2 data, bool debug = false)
|
||||
{
|
||||
// network.update();
|
||||
int timeout = millis() + 100;
|
||||
while ( network.available() && timeout > millis() )
|
||||
{
|
||||
RF24NetworkHeader header;
|
||||
network.read(header, &data, sizeof(data));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Serial.print("Received packet ");
|
||||
Serial.println(data.servoPositions[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
# remote
|
||||
|
||||
arduino code for remote control
|
||||
@@ -1,122 +0,0 @@
|
||||
#include "TransferDataStructure.h"
|
||||
|
||||
String getValue(String data, char separator, int index)
|
||||
{
|
||||
int found = 0;
|
||||
int strIndex[] = { 0, -1 };
|
||||
int maxIndex = data.length() - 1;
|
||||
|
||||
for (int i = 0; i <= maxIndex && found <= index; i++) {
|
||||
if (data.charAt(i) == separator || i == maxIndex) {
|
||||
found++;
|
||||
strIndex[0] = strIndex[1] + 1;
|
||||
strIndex[1] = (i == maxIndex) ? i + 1 : i;
|
||||
}
|
||||
}
|
||||
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||
}
|
||||
|
||||
dataStruct2 GetSerialData(dataStruct2 &dataIn, bool debug = false)
|
||||
{
|
||||
if (Serial.available() && Serial.peek() != -1)
|
||||
{
|
||||
// String data = Serial.readStringUntil('\r');
|
||||
// while (Serial.read() >= 0);
|
||||
// int maxIndex = data.length() - 1;
|
||||
// int index = 0;
|
||||
// int next_index;
|
||||
// String data_word;
|
||||
// String channel;
|
||||
// String angle;
|
||||
// do {
|
||||
// next_index = data.indexOf(',', index);
|
||||
//
|
||||
// data_word = data.substring(index, next_index);
|
||||
// channel = data_word.substring(0, data_word.indexOf('_'));
|
||||
// angle = data_word.substring(data_word.indexOf('_') + 1);
|
||||
//
|
||||
// if (isDigit(angle[0])) // prevent error overwriting first entry.
|
||||
// dataIn.servoPositions[channel.toInt()] = angle.toFloat();
|
||||
//
|
||||
// index = next_index + 1;
|
||||
// } while ((next_index != -1) && (next_index < maxIndex));
|
||||
|
||||
|
||||
/*String s = Serial.readStringUntil('s');
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
Serial.setTimeout(10);
|
||||
String c = Serial.readStringUntil('_');
|
||||
String v = Serial.readStringUntil(',');
|
||||
String cc = Serial.readStringUntil('=');
|
||||
int channel = c.toInt();
|
||||
int value = v.toInt();
|
||||
int crc = cc.toInt();
|
||||
|
||||
if ((crc == (channel) * value) && value >= 0 && value <= 180)
|
||||
dataIn.servoPositions[channel] = value;*/
|
||||
//byte recv[18 + 1];
|
||||
if (Serial.available() >= 18 + 1 + 2 + 30)
|
||||
{
|
||||
bool recc = false;
|
||||
byte recv[256] = {0};
|
||||
//Serial.readBytesUntil(0xffffff, recv, 255);
|
||||
Serial.readBytesUntil(0xff, recv, 255);
|
||||
for (int i = 0; i < 255 - 19; i++)
|
||||
{
|
||||
// if (recv[i + 1] == 0xff && recv[i + 2] == 0xff && recv[i + 3] == 0xff)
|
||||
if (recv[i + 19] == 0xfe)
|
||||
{
|
||||
for (int j = 0; j < 18 + 1; j++)
|
||||
{
|
||||
recv[j] = recv[(i) + j];
|
||||
}
|
||||
recc = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//s.getBytes(recv, s.length());
|
||||
byte crc = 0x00;
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
crc += recv[i];
|
||||
}
|
||||
|
||||
|
||||
if (crc == recv[18])
|
||||
{
|
||||
|
||||
if (recc)
|
||||
{
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
dataIn.servoPositions[i] = recv[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
dataIn.remotePasstroughControl = true;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Serial.println("Enabled Servo Passtrough mode!");
|
||||
|
||||
Serial.println("Output line: ");
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
Serial.print(i);
|
||||
Serial.print(", ");
|
||||
Serial.print(dataIn.servoPositions[i]);
|
||||
Serial.println("");
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dataIn;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#ifndef dataStruct
|
||||
#define dataStruct
|
||||
|
||||
struct __attribute__((__packed__)) dataStruct2
|
||||
{
|
||||
bool STOP = false;
|
||||
|
||||
float walkSpeed = 10; //step size
|
||||
float walkSpeed2 = 0; //gate speed
|
||||
float walkRotation = 0 ;
|
||||
float walkDirection = 0;
|
||||
|
||||
float tranform[3] = {0, 0, 0};
|
||||
float tranform2[3] = {0, 0, 0};
|
||||
float rotation[3] = {0, 0, 0};
|
||||
|
||||
bool remotePasstroughControl = 0;
|
||||
float servoPositions[18] = {
|
||||
90, 90, 90,
|
||||
90, 90, 90,
|
||||
90, 90, 90,
|
||||
|
||||
90, 90, 90,
|
||||
90, 90, 90,
|
||||
90, 90, 90
|
||||
};
|
||||
} dataStruct;
|
||||
|
||||
|
||||
//template<size_t ... T> struct print_ct {
|
||||
// print_ct() {
|
||||
// static_assert(sizeof...(T) == -1, "");
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//print_ct< sizeof(dataStruct2), alignof(dataStruct2) > v;
|
||||
|
||||
#endif
|
||||
@@ -1,176 +0,0 @@
|
||||
#include "Joysticks.h"
|
||||
#include "Nrf.h"
|
||||
#include "SerialPasstrough.h"
|
||||
#include <Wire.h>
|
||||
#include <MPU6050_tockn.h>
|
||||
#include "Nextion.h"
|
||||
|
||||
NexPage page0 = NexPage(4, 0, "uploadscreen");
|
||||
|
||||
NexText t0 = NexText(1, 6, "t1");
|
||||
NexText t1 = NexText(3, 22, "t1");
|
||||
|
||||
NexButton b2 = NexButton(1, 5, "b2");
|
||||
NexSlider sliders[18] = {NexSlider(3, 1, "h0"),
|
||||
NexSlider(3, 2, "h1"),
|
||||
NexSlider(3, 3, "h2"),
|
||||
NexSlider(3, 4, "h3"),
|
||||
NexSlider(3, 5, "h4"),
|
||||
NexSlider(3, 6, "h5"),
|
||||
NexSlider(3, 7, "h6"),
|
||||
NexSlider(3, 8, "h7"),
|
||||
NexSlider(3, 9, "h8"),
|
||||
NexSlider(3, 10, "h9"),
|
||||
NexSlider(3, 11, "h10"),
|
||||
NexSlider(3, 12, "h11"),
|
||||
NexSlider(3, 13, "h12"),
|
||||
NexSlider(3, 14, "h13"),
|
||||
NexSlider(3, 15, "h14"),
|
||||
NexSlider(3, 16, "h15"),
|
||||
NexSlider(3, 17, "h16"),
|
||||
NexSlider(3, 18, "h17")
|
||||
};
|
||||
|
||||
char buffer[100] = {0};
|
||||
|
||||
NexTouch *nex_listen_list[] =
|
||||
{
|
||||
&b2,
|
||||
&page0,
|
||||
&t0,
|
||||
&t1,
|
||||
NULL
|
||||
};
|
||||
|
||||
void b2PopCallback(void *ptr)
|
||||
{
|
||||
passtrough();
|
||||
}
|
||||
|
||||
MPU6050 mpu (Wire);
|
||||
|
||||
dataStruct2 data;
|
||||
joyStickdataStruct joystickData;
|
||||
|
||||
void setup() {
|
||||
// Serial.begin(250000, SERIAL_8E1); // ARDUINO
|
||||
Serial.begin(250000); // TEENSY
|
||||
// Serial.begin(115200);
|
||||
Serial1.begin(115200);
|
||||
// passtrough();
|
||||
|
||||
nexInit();
|
||||
b2.attachPush(b2PopCallback, &b2);
|
||||
b2.attachPop(b2PopCallback, &b2);
|
||||
// for (int i = 0; i < 18; i++)
|
||||
// sliders[i] = NexSlider(3, i++, "h" + i);
|
||||
// while (true)
|
||||
// {
|
||||
// nexLoop(nex_listen_list);
|
||||
// sliders[0].setValue(30);
|
||||
// }
|
||||
|
||||
// Initialization
|
||||
// Wire.begin();
|
||||
// mpu.begin();
|
||||
//
|
||||
// mpu.calcGyroOffsets(true, 300, 1000);
|
||||
//
|
||||
// // Calibration
|
||||
// Serial.println("=====================================");
|
||||
// Serial.println("Starting calibration...");
|
||||
// mpu.calcGyroOffsets();
|
||||
// Serial.println("Calibration complete!");
|
||||
|
||||
JoystickInit();
|
||||
|
||||
NrfInit();
|
||||
}
|
||||
|
||||
void passtrough()
|
||||
{
|
||||
delay(100);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
// nexLoop(nex_listen_list);
|
||||
// delay(10);
|
||||
page0.show();
|
||||
delay(10);
|
||||
}
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial1.begin(115200);
|
||||
do {
|
||||
if (Serial.available()) { // If anything comes in Serial (USB),
|
||||
Serial1.write(Serial.read()); // read it and send it out Serial1 (pins 0 & 1)
|
||||
}
|
||||
|
||||
if (Serial1.available()) { // If anything comes in Serial1 (pins 0 & 1)
|
||||
Serial.write(Serial1.read()); // read it and send it out Serial (USB)
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
nexLoop(nex_listen_list);
|
||||
network.update();
|
||||
|
||||
if (false)
|
||||
{
|
||||
mpu.update();
|
||||
Serial.print("AngX = ");
|
||||
Serial.print(mpu.getAngleX());
|
||||
Serial.print(" / AngY = ");
|
||||
Serial.print(mpu.getAngleY());
|
||||
Serial.print(" / AngZ = ");
|
||||
Serial.println(mpu.getAngleZ());
|
||||
}
|
||||
|
||||
// Serial.print(" / AngX = ");
|
||||
// Serial.print(mpu.getGyroAngleX());
|
||||
// Serial.print(" / AngY = ");
|
||||
// Serial.print(mpu.getGyroAngleY());
|
||||
// Serial.print(" / AngZ = ");
|
||||
// Serial.println(mpu.getGyroAngleZ());
|
||||
|
||||
joystickData = JoystickGet(true);
|
||||
|
||||
// test
|
||||
if (false)
|
||||
{
|
||||
data.remotePasstroughControl = true;
|
||||
data.servoPositions[1] = (joystickData.value[2] * 0.78f);
|
||||
data.servoPositions[4] = (joystickData.value[2] * 0.78f);
|
||||
data.servoPositions[7] = (joystickData.value[2] * 0.78f);
|
||||
|
||||
data.servoPositions[10] = 180 - (joystickData.value[2] * 0.78f);
|
||||
data.servoPositions[13] = 180 - (joystickData.value[2] * 0.78f);
|
||||
data.servoPositions[16] = 180 - (joystickData.value[2] * 0.78f);
|
||||
}
|
||||
|
||||
GetSerialData(data, false);
|
||||
// data = GetSerialData(data, false);
|
||||
|
||||
// data.STOP = true;
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
sliders[i].setValue(data.servoPositions[i]);
|
||||
|
||||
bool ok = NrfSendData(data, false);
|
||||
// data = NrfSendData(data, false);
|
||||
|
||||
if (ok)
|
||||
t0.setText("connected");
|
||||
else
|
||||
t0.setText("not connected");
|
||||
if (ok)
|
||||
t1.setText("connected");
|
||||
else
|
||||
t1.setText("not connected");
|
||||
|
||||
//test
|
||||
// data = NrfGetData(data, true);
|
||||
|
||||
delay(20);
|
||||
}
|
||||
@@ -9,10 +9,14 @@ remote/ remote firmware: 2 x 3-axis sticks, MPU6050 tilt, Nex
|
||||
shared/ HexapodProtocol: the CmdPacket wire format + radio settings used by both
|
||||
sim/ the unchanged robot firmware compiled into a DLL for the simulation
|
||||
Hexapod_Simulation_Unity/ Unity project that runs that DLL on the 3D model
|
||||
LEGACY/ older material kept for reference
|
||||
hardware/fusion360/ Fusion 360 designs: body, legs, servo, servo horn, remote case
|
||||
scripts/ PlatformIO helper (per-environment sketch folder)
|
||||
```
|
||||
|
||||
This is the `2026-current/` folder of the hexapod-robot repo; the earlier
|
||||
generations (2009 onwards) are in the folders next to it, see
|
||||
[../README.md](../README.md).
|
||||
|
||||
## Build (PlatformIO)
|
||||
|
||||
```
|
||||
@@ -24,7 +28,7 @@ pio device monitor -e robot
|
||||
|
||||
## Simulation
|
||||
|
||||
From the repo root in PowerShell (the dev PC is Windows):
|
||||
From this `2026-current` folder in PowerShell (the dev PC is Windows):
|
||||
|
||||
```
|
||||
.\sim\build.ps1 # build hexapod_sim.dll + run the headless firmware checks
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
constexpr float TX_HZ = 100.0f;
|
||||
|
||||
// ---- Radio (nRF24L01) on SPI0: MOSI 11, MISO 12, SCK 13 ----
|
||||
// CE/CSN as in the old remote sketch (LEGACY/remote/teensy/Nrf.h).
|
||||
// CE/CSN as in the old remote sketch (2019-teensy-nrf24/remote/Nrf.h).
|
||||
constexpr uint8_t RADIO_CE_PIN = 9;
|
||||
constexpr uint8_t RADIO_CSN_PIN = 10;
|
||||
// Auto-retransmit: (delay units of 250us, count). Kept short on purpose - a
|
||||
@@ -31,7 +31,7 @@ constexpr uint32_t LINK_LOST_MS = 300;
|
||||
// Logical axis order used everywhere in the remote code.
|
||||
enum StickAxis : uint8_t { L_X = 0, L_Y, L_TWIST, R_X, R_Y, R_TWIST, NUM_AXES };
|
||||
|
||||
// A0-A5 in a row, as wired for the old remote (LEGACY/remote/teensy/Joysticks.h).
|
||||
// A0-A5 in a row, as wired for the old remote (2019-teensy-nrf24/remote/Joysticks.h).
|
||||
// A4/A5 are also Wire's SDA/SCL - that's why the MPU6050 is on Wire2 below.
|
||||
// BENCH: which physical axis is on which pin wasn't recoverable from the old
|
||||
// code; reorder these so each lands on the right logical axis ('p' dump).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Nextion HMI build guide
|
||||
|
||||
Start from your existing HMI (`LEGACY/remote/remote.HMI`, the servo
|
||||
Start from your existing HMI (`../../2019-teensy-nrf24/remote-nextion/remote.HMI`, the servo
|
||||
monitor) and **add one page named `control`** with the components below.
|
||||
Your existing pages keep working:
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ at 100 Hz.
|
||||
|
||||
## Building
|
||||
|
||||
From the repo root: `pio run -e remote`, flash with
|
||||
From the `2026-current` folder: `pio run -e remote`, flash with
|
||||
`pio run -e remote -t upload`, monitor with `pio device monitor -e remote`.
|
||||
|
||||
## Wiring (from the old remote sketch in `LEGACY/remote/teensy/`; edit `Config.h` if yours differs)
|
||||
## Wiring (from the old remote sketch in `../../2019-teensy-nrf24/remote/`; edit `Config.h` if yours differs)
|
||||
|
||||
| Part | Signal | Teensy 4.1 pin |
|
||||
|------|--------|----------------|
|
||||
|
||||
@@ -32,7 +32,7 @@ mistakes.
|
||||
|
||||
Needs a 64-bit g++ and CMake. Strawberry Perl's `C:\Strawberry\c\bin` has
|
||||
g++, cmake and ninja, and the script falls back to it automatically. From
|
||||
the repo root in PowerShell:
|
||||
the `2026-current` folder in PowerShell:
|
||||
|
||||
```
|
||||
.\sim\build.ps1 # configure (first time) + build + smoke test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Builds the firmware simulation DLL and runs the headless smoke test.
|
||||
# Windows PowerShell 5.1 compatible. From the repo root:
|
||||
# Windows PowerShell 5.1 compatible. From the 2026-current folder:
|
||||
#
|
||||
# .\sim\build.ps1 configure (first time) + build + smoke test
|
||||
# .\sim\build.ps1 -NoTest build only
|
||||
|
||||
Reference in new issue
Block a user