fix height error and implement hadr25 tree

This commit is contained in:
interfisch 2025-07-18 22:53:12 +02:00
parent 0a24dae76c
commit 7e437daf75
13 changed files with 195 additions and 53 deletions

View file

@ -166,7 +166,7 @@ void setup() {
//myPort = new Serial(this, "COM3", 115200);
myPort = new Serial(this, "/dev/ttyUSB0", 115200);
myPort = new Serial(this, "/dev/ttyACM0", 115200);
}
void Set() {

View file

@ -26,7 +26,7 @@ lib_deps =
build_flags =
-D PIXELPIN=4
-D NUMPIXELS=600
[env:d1_mini]
platform = espressif8266
board = d1_mini

64
src/espnow.cpp Normal file
View file

@ -0,0 +1,64 @@
#ifdef DEACTIVATED
#include "espnow.h"
//Mac Adress Receiver: 24:58:7c:cd:a8:c4
// Create a struct_message
struct_message espnowdata;
void readMacAddress(){
uint8_t baseMac[6];
esp_err_t ret = esp_wifi_get_mac(WIFI_IF_STA, baseMac);
if (ret == ESP_OK) {
Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
baseMac[0], baseMac[1], baseMac[2],
baseMac[3], baseMac[4], baseMac[5]);
} else {
Serial.println("Failed to read MAC address");
}
}
void initESPNOW() {
WiFi.mode(WIFI_STA);
WiFi.begin();
Serial.print("[DEFAULT] ESP32 Board MAC Address: ");
readMacAddress();
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&espnowdata, incomingData, sizeof(espnowdata));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print(" Command: ");
Serial.println(espnowdata.cmd);
statuspixel.setPixelColor(0, statuspixel.Color((millis()%3==0)*255,(millis()%3==1)*255,(millis()%3==2)*255)); //change status led when packet arrives
statuspixel.show();
processCommand(&espnowdata);
Serial.println();
}
#endif

45
src/espnow.h Normal file
View file

@ -0,0 +1,45 @@
#ifdef DEACTIVATED //deactivated to compile again without espnow
#ifndef espnow_h
#define espnow_h
#include <WiFi.h>
#include <esp_wifi.h>
#include <esp_now.h>
#include <Adafruit_NeoPixel.h>
extern Adafruit_NeoPixel statuspixel;
extern void processCommand(struct_message espnowdata);
void readMacAddress();
void initESPNOW();
// Must match the receiver structure
enum command { findled, setheight, resetheightmap, saveheightmap };
/*
findled: a=lednum, b=unused
setheight: a=lednum,b=height
resetheightmap: a=23, b=42
saveheightmap: a=24, b=43
*/
typedef struct struct_message {
command cmd;
int a;
int b;
} struct_message;
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len);
#endif
#endif

View file

@ -1,7 +1,7 @@
#include "fx_flash.h"
#include "effect.h"
FX_Flash::FX_Flash(int numpixels,Adafruit_NeoPixel *strip,uint8_t *height,uint32_t flashcolor)
FX_Flash::FX_Flash(int numpixels,Adafruit_NeoPixel *strip,uint16_t *height,uint32_t flashcolor)
{
_numpixels=numpixels;
_strip=strip;

View file

@ -7,7 +7,7 @@
class FX_Flash : public Effect
{
public:
FX_Flash(int numpixels,Adafruit_NeoPixel *strip,uint8_t *height,uint32_t flashcolor);
FX_Flash(int numpixels,Adafruit_NeoPixel *strip,uint16_t *height,uint32_t flashcolor);
FX_Flash();
void updateRoutine(float updatedelayms);
void updateGraphics();
@ -20,7 +20,7 @@ class FX_Flash : public Effect
long _starttime;
uint8_t _brightness;
long _flashtime;
uint8_t *_height;
uint16_t *_height;
};
#endif

View file

@ -1,7 +1,7 @@
#include "fx_scanner.h"
#include "effect.h"
FX_Scanner::FX_Scanner(int numpixels,Adafruit_NeoPixel *strip,uint8_t *height,int startpos,float scannervel,uint32_t scannercolor)
FX_Scanner::FX_Scanner(int numpixels,Adafruit_NeoPixel *strip,uint16_t *height,int startpos,float scannervel,uint32_t scannercolor)
{
_numpixels=numpixels;
_pos = startpos;

View file

@ -7,7 +7,7 @@
class FX_Scanner : public Effect
{
public:
FX_Scanner(int numpixels,Adafruit_NeoPixel *strip,uint8_t *height,int startpos,float scannervel,uint32_t scannercolor);
FX_Scanner(int numpixels,Adafruit_NeoPixel *strip,uint16_t *height,int startpos,float scannervel,uint32_t scannercolor);
FX_Scanner();
void updateRoutine(float updatedelayms);
void updateGraphics();
@ -18,7 +18,7 @@ class FX_Scanner : public Effect
Adafruit_NeoPixel *_strip;
float _pos;
float _vel;
uint8_t *_height;
uint16_t *_height;
uint32_t _scannercolor;
};

View file

@ -1,7 +1,7 @@
#include "fx_shootingstar.h"
#include "effect.h"
FX_ShootingStar::FX_ShootingStar(int numpixels,Adafruit_NeoPixel *strip,uint8_t *height)
FX_ShootingStar::FX_ShootingStar(int numpixels,Adafruit_NeoPixel *strip,uint16_t *height)
{
_numpixels=numpixels;
_strip=strip;

View file

@ -7,7 +7,7 @@
class FX_ShootingStar : public Effect
{
public:
FX_ShootingStar(int numpixels,Adafruit_NeoPixel *strip,uint8_t *height);
FX_ShootingStar(int numpixels,Adafruit_NeoPixel *strip,uint16_t *height);
FX_ShootingStar();
void updateRoutine(float updatedelayms);
void updateGraphics();
@ -19,7 +19,7 @@ class FX_ShootingStar : public Effect
long _starttime;
uint8_t _brightness;
long _duration;
uint8_t *_height;
uint16_t *_height;
int _pos;
float _vel;
};

View file

@ -1,5 +1,7 @@
#include <Arduino.h>
//#include "espnow.h" //TODO
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
@ -36,7 +38,6 @@ void saveHeightmapRaw();
#ifdef PIN_NEOPIXEL
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel statuspixel(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
#endif
@ -68,9 +69,9 @@ unsigned long last_ldrread=0;
long loopmillis=0;
uint8_t height[NUMPIXELS];
uint8_t heightraw[NUMPIXELS]; //uninterpolated values
#define MAXHEIGHT 254
uint16_t height[NUMPIXELS];
uint16_t heightraw[NUMPIXELS]; //uninterpolated values
#define MAXHEIGHT 350
std::vector <Wagon> wagon_arr;
uint8_t maxid=0;
@ -108,6 +109,8 @@ long last_changePersistancemode=0;
void setup() {
Serial.begin(115200);
//initESPNOW(); //todo, deactivated to compile
#ifdef PIN_LDR
pinMode(PIN_LDR, INPUT);
#endif
@ -156,19 +159,40 @@ void setup() {
resetHeightmap();
loadHeightmapRaw();
//loadHeightmapRaw();
heightraw[0]=0;
heightraw[50]=96;
heightraw[64]=103;
heightraw[87]=100;
heightraw[107]=120;
heightraw[155]=199;
heightraw[185]=220;
heightraw[238]=184;
heightraw[269]=209;
heightraw[290]=187;
heightraw[318]=120;
heightraw[358]=187;
heightraw[385]=135;
heightraw[408]=114;
heightraw[464]=203;
heightraw[494]=240;
heightraw[502]=243;
heightraw[506]=240;
heightraw[550]=203;
heightraw[574]=188;
heightraw[599]=199;
interpolateHeightValues();
/*
Serial.println();
for (int i=0;i<NUMPIXELS;i++){
Serial.print(i);
Serial.print(": ");
Serial.println(height[i]);
}*/
}
@ -180,10 +204,10 @@ void setup() {
}
#define NEEDS_INTERPOLATION 65535
void resetHeightmap(){
for (int i=0;i<NUMPIXELS;i++){
heightraw[i]=255; //255 means value need to be interpolated
heightraw[i]=NEEDS_INTERPOLATION;
}
heightraw[0]=0;
heightraw[NUMPIXELS-1]=0;
@ -192,7 +216,7 @@ void resetHeightmap(){
void printHeightmapRaw() {
Serial.println();
for (int i=0;i<NUMPIXELS;i++){
if (heightraw[i]!=255){
if (heightraw[i]!=NEEDS_INTERPOLATION){
Serial.print("heightraw[");
Serial.print(i);
Serial.print("]=");
@ -209,18 +233,18 @@ void interpolateHeightValues(){
}
//interpolate every part with height value 255
for (int interpolateStartpos=0;interpolateStartpos<NUMPIXELS-1;interpolateStartpos++){
if (height[interpolateStartpos]==255){ //interpolation part starts
if (height[interpolateStartpos]==NEEDS_INTERPOLATION){ //interpolation part starts
int interpolateEndpos=interpolateStartpos+1;
while (interpolateEndpos<NUMPIXELS && height[interpolateEndpos]==255){
while (interpolateEndpos<NUMPIXELS && height[interpolateEndpos]==NEEDS_INTERPOLATION){
interpolateEndpos++;
}
interpolateEndpos--;
//interpolateStartpos index of first 255 value
//interpolateEndpos index of last 255 value
//interpolateStartpos index of first NEEDS_INTERPOLATION value
//interpolateEndpos index of last NEEDS_INTERPOLATION value
uint8_t interpolateStartvalue=height[interpolateStartpos-1];
uint8_t interpolateEndvalue=height[interpolateEndpos+1];
int interpolateLength=interpolateEndpos-interpolateStartpos+1; //one 255 element -> length 1
int interpolateLength=interpolateEndpos-interpolateStartpos+1; //one NEEDS_INTERPOLATION element -> length 1
float interpolateStep= ((int)(interpolateEndvalue)-(int)(interpolateStartvalue))*1.0 /(interpolateLength+1);
Serial.println();
Serial.print("interpolateStep=");
@ -267,10 +291,11 @@ void interpolateHeightValues(){
void previewHeightmap(int waittime){
for (int i=0;i<NUMPIXELS;i++){
//uint32_t c=Wheel(height[i]*255/45);
uint8_t b=height[i]*255.0/MAXHEIGHT;
//uint8_t b=height[i]*255.0/MAXHEIGHT;
uint8_t b=height[i];
//uint32_t c=strip.Color(255-b,b,0);
uint32_t c=Wheel(b/1.2);
if (height[i]==255){
if (height[i]==NEEDS_INTERPOLATION){
c=strip.Color(0,0,0);
}
strip.setPixelColor(i,c);
@ -304,24 +329,26 @@ void spawnWagon(){
// pos, wagonlength, startvel , startacc, trainmass, wagoncolor
//Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, random(0, 20), _randomlength, random(map(_randomlength,3,40,1,1), map(_randomlength,3,40, 13,40))/10.0 , 0 , 5 , Wheel((uint8_t)random(0,255))); //spawn new wagon
int side_startpos=0; //start at beginning of strip
int side_multi=1; //start in forward direction
/*if (random(0,2)==0){ //spawn from other side
side_startpos=NUMPIXELS+_randomlength;
side_multi=-1;
}*/
int side_startpos=0; //0=start at beginning of strip
int side_multi=1; //1=start in forward direction
#ifdef REVERSE_DIRECTION
//Force start from end of strip
side_startpos=NUMPIXELS+_randomlength; //start at end of strip
side_multi=-1; //start in backward direction
#endif
#ifdef RANDOM_DIRECTION
if (random(0,2)==0){ //spawn from other side
side_startpos=NUMPIXELS+_randomlength;
side_multi=-1;
}
#endif
//Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, side_startpos, _randomlength, side_multi*random(map(_randomlength,3,30,0,40)/10.0, map(_randomlength,3,30, 5,60))/10.0 , 0 , random(3.0,7.0) , Wheel((uint8_t)random(0,255))); //spawn new wagon
//Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, side_startpos, _randomlength, side_multi*random(map(_randomlength,3,30,30,100)/10.0, map(_randomlength,3,30, 5,60))/10.0 , 0 , 1.8 , Wheel((uint8_t)random(0,255))); //spawn new wagon
Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, side_startpos, _randomlength, side_multi*random(0,random(10,60))/10.0 , 0 , random(2,5)/10.0 , Wheel((uint8_t)random(0,255))); //spawn new wagon . start from near standstill
//Mass: the lighter the faster is changes speed
//Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, side_startpos, _randomlength, side_multi*random(map(_randomlength,3,40,30,80)/10.0, map(_randomlength,3,40, 5,60))/10.0 , 0 , 1.8 , Wheel((uint8_t)random(0,255))); //spawn new wagon
Wagon tmpr = Wagon(maxid++,NUMPIXELS,&strip, height, side_startpos, _randomlength, side_multi*random(20,70)/10.0 , 0 , map(_randomlength,3,40,2.0,1.0) , Wheel((uint8_t)random(0,255))); //spawn new wagon
//Mass: the heavier the faster is changes speed
@ -372,7 +399,11 @@ void loop() {
}
/*
void processCommand(struct_message espnowdata) { //espnow data from remote
espnowdata.cmd //TODO
}
*/
void checkSerial(){
static String serialstring_temp="";
@ -394,8 +425,6 @@ void checkSerial(){
if (serialstring.length()>0) {
Serial.println("String:"+serialstring);
if (serialstring.equals("run")){
strip.setBrightness(BRIGHTNESS_RUN);
configmode=false;
@ -648,7 +677,8 @@ void loop_achterbahn(){
//Check spawning
#define AUTOSPAWN
#ifdef AUTOSPAWN
if (lastCheckspawn+CHECKSPAWNDELAY<loopmillis) {
lastCheckspawn=loopmillis;
Serial.print("Checking Spawning, wagons ");
@ -660,6 +690,7 @@ void loop_achterbahn(){
}
}
}
#endif
//Check Effect Spawning
@ -708,9 +739,11 @@ uint32_t Wheel(byte WheelPos) {
void loadHeightmapRaw(){
int c_eepromaddress=EEPROMSTARTADDRESS_HEIGHTMAP;
uint8_t lastvalue=0;
uint16_t lastvalue=0;
for (int i=0;i<NUMPIXELS;i++){
lastvalue = EEPROM.read(c_eepromaddress);
lastvalue = EEPROM.read(c_eepromaddress); //lowbyte
c_eepromaddress++;
lastvalue += EEPROM.read(c_eepromaddress)<<8; //highbyte
heightraw[i]=lastvalue;
c_eepromaddress++;
}
@ -720,9 +753,9 @@ void loadHeightmapRaw(){
void saveHeightmapRaw(){
int c_eepromaddress=EEPROMSTARTADDRESS_HEIGHTMAP;
for (int i=0;i<NUMPIXELS;i++){
EEPROM.write(c_eepromaddress, heightraw[i]); //address, value
c_eepromaddress++;
EEPROM.write(c_eepromaddress, (byte)heightraw[i]); //address, value, lowbyte
EEPROM.write(c_eepromaddress, (byte)(heightraw[i]>>8)); //address, value, highbyte
c_eepromaddress++;
}
Serial.println("Saved to EEPROM");
EEPROM.commit(); //write changes to eeprom. EEPROM.end() will also commit and release the ram copy of eeprom contents

View file

@ -30,7 +30,7 @@
191,193,194,196,198,200,202,204,206,208,210,212,214,216,218,220,
222,224,227,229,231,233,235,237,239,241,244,246,248,250,252,255}; */
Wagon::Wagon(int id,int numpixels, Adafruit_NeoPixel *strip,uint8_t *height,float pos, float trainlength,float startvel,float startacc, float wagonmass, uint32_t wagoncolor)
Wagon::Wagon(int id,int numpixels, Adafruit_NeoPixel *strip,uint16_t *height,float pos, float trainlength,float startvel,float startacc, float wagonmass, uint32_t wagoncolor)
{
_id = id;
_numpixels=numpixels;

View file

@ -7,7 +7,7 @@ class Wagon
{
public:
int _id;
Wagon(int id,int numpixels,Adafruit_NeoPixel *strip,uint8_t *height, float pos, float wagonlength, float startvel,float startacc, float wagonmass, uint32_t wagoncolor);
Wagon(int id,int numpixels,Adafruit_NeoPixel *strip,uint16_t *height, float pos, float wagonlength, float startvel,float startacc, float wagonmass, uint32_t wagoncolor);
Wagon();
bool operator==(const Wagon &r) const;
void updatePhysics(float updatedelayms);
@ -28,7 +28,7 @@ class Wagon
float _acc;
float _wagonmass;
float _trainlength;
uint8_t *_height;
uint16_t *_height;
long _spawntime;
float _lastvel;
float _lastpositivedirchangepos;