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
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.
Binary file not shown.
Binary file not shown.
LFS
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
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