Wired train control working
This commit is contained in:
parent
dd5cabbf05
commit
8b8891a605
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "Syren50.h"
|
||||||
|
|
||||||
|
void Syren50::init() {
|
||||||
|
Serial1.begin(9600);
|
||||||
|
delay(1000); // Give about 1 second to boot up, per datasheet
|
||||||
|
Serial.write(0b10101010);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Syren50::command(uint8_t command, uint8_t data) {
|
||||||
|
Serial1.write(0x80); // Address
|
||||||
|
Serial1.write(command); // Command
|
||||||
|
Serial1.write(data);
|
||||||
|
Serial1.write((0x80 + command + data) & 0b01111111); // Checksum
|
||||||
|
Serial1.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Syren50::forwards(uint8_t speed) {
|
||||||
|
command(0x00, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Syren50::reverse(uint8_t speed) {
|
||||||
|
command(0x01, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Syren50::move(int8_t direction, uint8_t speed) {
|
||||||
|
if (direction == 1) {
|
||||||
|
forwards(speed);
|
||||||
|
} else if (direction == -1) {
|
||||||
|
reverse(speed);
|
||||||
|
} else {
|
||||||
|
forwards(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Syren50::minInputVoltage(float voltage) {
|
||||||
|
command(0x03, (uint8_t)((voltage - 6.0) * 5.0));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef SYREN50_H
|
||||||
|
#define SYREN50_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class Syren50 {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void forwards(uint8_t speed);
|
||||||
|
void reverse(uint8_t speed);
|
||||||
|
void move(int8_t direction, uint8_t speed);
|
||||||
|
void minInputVoltage(float voltage);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void command(uint8_t command, uint8_t data);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -9,9 +9,23 @@
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
default_envs = default
|
default_envs = esp12e
|
||||||
name = RemoteTrainControl
|
name = RemoteTrainControl
|
||||||
|
|
||||||
[env:default]
|
[env:esp12e]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
|
framework = arduino
|
||||||
board = esp12e
|
board = esp12e
|
||||||
|
lib_deps =
|
||||||
|
adafruit/Adafruit ADS1X15@^2.4.0
|
||||||
|
SPI
|
||||||
|
adafruit/Adafruit SSD1306@^2.5.7
|
||||||
|
|
||||||
|
[env:nodemcuv2]
|
||||||
|
platform = espressif8266
|
||||||
|
framework = arduino
|
||||||
|
board = nodemcuv2
|
||||||
|
lib_deps =
|
||||||
|
adafruit/Adafruit ADS1X15@^2.4.0
|
||||||
|
SPI
|
||||||
|
adafruit/Adafruit SSD1306@^2.5.7
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 128 // OLED display width, in pixels
|
||||||
|
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
|
||||||
|
|
||||||
|
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
|
||||||
|
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
|
||||||
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||||
|
|
||||||
|
void testdrawrect(void) {
|
||||||
|
display.clearDisplay();
|
||||||
|
|
||||||
|
for(int16_t i=0; i<display.height()/2; i+=2) {
|
||||||
|
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
|
||||||
|
display.display(); // Update screen with each newly-drawn rectangle
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testfillrect(void) {
|
||||||
|
display.clearDisplay();
|
||||||
|
|
||||||
|
for(int16_t i=0; i<display.height()/2; i+=3) {
|
||||||
|
// The INVERSE color is used so rectangles alternate white/black
|
||||||
|
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
|
||||||
|
display.display(); // Update screen with each newly-drawn rectangle
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testdrawchar(void) {
|
||||||
|
display.clearDisplay();
|
||||||
|
|
||||||
|
display.setTextSize(1); // Normal 1:1 pixel scale
|
||||||
|
display.setTextColor(SSD1306_WHITE); // Draw white text
|
||||||
|
display.setCursor(0, 0); // Start at top-left corner
|
||||||
|
display.cp437(true); // Use full 256 char 'Code Page 437' font
|
||||||
|
|
||||||
|
// Not all the characters will fit on the display. This is normal.
|
||||||
|
// Library will draw what it can and the rest will be clipped.
|
||||||
|
for(int16_t i=0; i<256; i++) {
|
||||||
|
if(i == '\n') display.write(' ');
|
||||||
|
else display.write(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
display.display();
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testdrawstyles(void) {
|
||||||
|
display.clearDisplay();
|
||||||
|
|
||||||
|
display.setTextSize(1); // Normal 1:1 pixel scale
|
||||||
|
display.setTextColor(SSD1306_WHITE); // Draw white text
|
||||||
|
display.setCursor(0,0); // Start at top-left corner
|
||||||
|
display.println(F("Hello, world!"));
|
||||||
|
|
||||||
|
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
|
||||||
|
display.println(3.141592);
|
||||||
|
|
||||||
|
display.setTextSize(2); // Draw 2X-scale text
|
||||||
|
display.setTextColor(SSD1306_WHITE);
|
||||||
|
display.print(F("0x")); display.println(0xDEADBEEF, HEX);
|
||||||
|
|
||||||
|
display.display();
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
|
||||||
|
|
||||||
|
|
||||||
|
// Draw a single pixel in white
|
||||||
|
display.drawPixel(10, 10, SSD1306_WHITE);
|
||||||
|
|
||||||
|
// Show the display buffer on the screen. You MUST call display() after
|
||||||
|
// drawing commands to make them visible on screen!
|
||||||
|
display.display();
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
testdrawrect(); // Draw rectangles (outlines)
|
||||||
|
testfillrect(); // Draw rectangles (filled)
|
||||||
|
testdrawchar(); // Draw characters of the default font
|
||||||
|
testdrawstyles(); // Draw 'stylized' characters
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_ADS1X15.h>
|
||||||
|
|
||||||
|
Adafruit_ADS1115 ads1115;
|
||||||
|
|
||||||
|
void controlsInit() {
|
||||||
|
ads1115.begin();
|
||||||
|
ads1115.setGain(GAIN_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
float map(float x, float in_min, float in_max, float out_min, float out_max)
|
||||||
|
{
|
||||||
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getControlsState(float &throttle, int &direction, bool &horn, bool &bell, bool &lights) {
|
||||||
|
float throttle_volts = ads1115.computeVolts(ads1115.readADC_SingleEnded(0));
|
||||||
|
float direction_volts = ads1115.computeVolts(ads1115.readADC_SingleEnded(1));
|
||||||
|
|
||||||
|
float throt = map(throttle_volts, 1.0f, 2.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
if (throt > 1.0f) {
|
||||||
|
throt = 1.0f;
|
||||||
|
}
|
||||||
|
if (throt < 0.0f) {
|
||||||
|
throt = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction_volts < 3.3/3.0) {
|
||||||
|
direction = -1;
|
||||||
|
throttle = throt;
|
||||||
|
} else if (direction_volts > (3.3 / 3.0) * 2.0) {
|
||||||
|
direction = 1;
|
||||||
|
throttle = throt;
|
||||||
|
} else {
|
||||||
|
direction = 0;
|
||||||
|
}
|
||||||
|
horn = false;
|
||||||
|
bell = false;
|
||||||
|
lights = false;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef CONTROLS_H
|
||||||
|
#define CONTROLS_H
|
||||||
|
|
||||||
|
void controlsInit();
|
||||||
|
float map(float x, float in_min, float in_max, float out_min, float out_max);
|
||||||
|
void getControlsState(float &throttle, int &direction, bool &horn, bool &bell, bool &lights);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "screen.h"
|
||||||
|
#include "wifi.h"
|
||||||
|
#include "controls.h"
|
||||||
|
#include "Syren50.h"
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
Syren50 motor;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
displayInit();
|
||||||
|
controlsInit();
|
||||||
|
WiFi.softAP(WIFI_SSID, WIFI_PASS);
|
||||||
|
displayWiFiInformation(WIFI_SSID, WIFI_PASS);
|
||||||
|
delay(1000);
|
||||||
|
motor.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
float throttle = 0.0f;
|
||||||
|
int direction = 0;
|
||||||
|
bool horn = false;
|
||||||
|
bool bell = false;
|
||||||
|
bool lights = false;
|
||||||
|
|
||||||
|
int last_direction = 0;
|
||||||
|
float last_throttle = 0.0f;
|
||||||
|
|
||||||
|
void inertia(float throttle, int direction, float &inertial_throttle, int &inertial_direction) {
|
||||||
|
|
||||||
|
inertial_throttle = throttle;
|
||||||
|
inertial_direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
getControlsState(throttle, direction, horn, bell, lights);
|
||||||
|
|
||||||
|
float motor_throttle;
|
||||||
|
int motor_direction;
|
||||||
|
inertia(throttle, direction, motor_throttle, motor_direction);
|
||||||
|
|
||||||
|
displayControlStatus(motor_throttle, motor_direction, horn, bell, lights);
|
||||||
|
motor.move(motor_direction, motor_throttle * 127.0f);
|
||||||
|
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 128
|
||||||
|
#define SCREEN_HEIGHT 32
|
||||||
|
|
||||||
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
|
||||||
|
|
||||||
|
bool displayEnabled = false;
|
||||||
|
|
||||||
|
void displayInit() {
|
||||||
|
displayEnabled = display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
|
||||||
|
if(displayEnabled) {
|
||||||
|
display.clearDisplay();
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayString(string inputString) {
|
||||||
|
if (!displayEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (char c: inputString) {
|
||||||
|
display.write(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayWiFiInformation(string wifiSSID, string wifiPassword) {
|
||||||
|
if (!displayEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setTextColor(SSD1306_WHITE);
|
||||||
|
display.setCursor(0,0);
|
||||||
|
displayString("WiFi Information:");
|
||||||
|
display.setCursor(0,8);
|
||||||
|
displayString("SSID: ");
|
||||||
|
displayString(wifiSSID);
|
||||||
|
display.setCursor(0,16);
|
||||||
|
displayString("Pass: ");
|
||||||
|
displayString(wifiPassword);
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayDirection(int &direction) {
|
||||||
|
if (direction == 0) {
|
||||||
|
displayString("N");
|
||||||
|
} else if (direction == 1) {
|
||||||
|
displayString("F");
|
||||||
|
} else if (direction == -1) {
|
||||||
|
displayString("R");
|
||||||
|
} else {
|
||||||
|
displayString("?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayBool(bool &state) {
|
||||||
|
if (state) {
|
||||||
|
displayString("1");
|
||||||
|
} else {
|
||||||
|
displayString("0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void displayControlStatus(float &throttle, int &direction, bool &horn, bool &bell, bool &lights) {
|
||||||
|
if (!displayEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.setTextColor(SSD1306_WHITE);
|
||||||
|
display.setCursor(0,0);
|
||||||
|
displayString("Throttle: ");
|
||||||
|
display.println(throttle * 100.0f);
|
||||||
|
displayString("%");
|
||||||
|
display.setCursor(0,8);
|
||||||
|
displayString("Direction: ");
|
||||||
|
displayDirection(direction);
|
||||||
|
display.setCursor(0,16);
|
||||||
|
displayString("H B L ");
|
||||||
|
display.setCursor(0,24);
|
||||||
|
displayBool(horn);
|
||||||
|
displayString(" ");
|
||||||
|
displayBool(bell);
|
||||||
|
displayString(" ");
|
||||||
|
displayBool(lights);
|
||||||
|
displayString(" ");
|
||||||
|
display.println((uint8_t)(throttle * 127.0f));
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef SCREEN_H
|
||||||
|
#define SCREEN_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void displayInit();
|
||||||
|
void displayString(string inputString);
|
||||||
|
void displayWiFiInformation(string wifiSSID, string wifiPassword);
|
||||||
|
void displayDirection(int &direction);
|
||||||
|
void displayBool(bool &state);
|
||||||
|
void displayControlStatus(float &throttle, int &direction, bool &horn, bool &bell, bool &lights);
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue