Modified remote - single board

Forum about the OS-Railway project available on Thingiverse. Here you can ask questions, look at building pictures, share ideas, pictures and STL's.
sidneylopsides
Posts: 12
Joined: Sun May 17, 2020 4:33 pm

Modified remote - single board

Postby sidneylopsides » Mon May 18, 2020 11:27 am

Hi!

I've updated the code to work on the TTGO TFT board, it's a cheap ESP32 board with 1.14" TFT, USB C and built in Lipo charging. It comes with a battery lead to connect to a lipo cell and then handles charging itself.

https://www.aliexpress.com/i/4000111532519.html

I've no potentiometers, some should be delivered today, but just doing a quick remap to the two on board buttons I can can control direction so it seems to all work fine. I'm not experiencing the long delay in actions that I get when using a phone of PC to control a train.

I've got some old small cells from indoor hobby quadcopters, so I'll use one of those on it.

You have to modify the tft library as shown here
https://github.com/Xinyuan-LilyGO/TTGO-T-Display

Code: Select all


/*
 *  This sketch demonstrates how to scan WiFi networks. 
 *  The API is almost the same as with the WiFi Shield library, 
 *  the most obvious difference being the different file you need to include:
 */
#include "WiFi.h"
#include <WiFiClient.h>

// We need to include Wire.h for I2C communication
#include <Wire.h>
//#include "OLED.h"
#include <string.h>
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();  // Invoke library, pins defined in User_Setup.h


const char* ssid = "OSR-Y1";
const char* password = "osrailway";


const char* host = "192.168.4.1";
const int httpsPort = 80;
const char* streamId   = "....................";
const char* privateKey = "....................";

bool isRunning = false;

#define button_forward  0         //Button for manual control
#define button_reverse  35         //Button for manual control
#define button_lightson  13         //Button for manual control
#define button_lightsoff  12         //Button for manual control
#define button_stop  1         //Button for manual control
#define button_aux  3         //Button for manual control

#define wheel A0


// Declare OLED tft
// tft(SDA, SCL);
// SDA and SCL are the GPIO pins of ESP8266 that are connected to respective pins of tft.
//OLED tft(4, 5);

int r = 0, c = 0;
char t;
char text[20];
int text_size;
int value = 0;

void setup() {
  Serial.begin(115200);
  pinMode(button_forward, INPUT_PULLUP); 
  pinMode(button_reverse, INPUT_PULLUP);
  pinMode(button_lightson, INPUT_PULLUP);
  pinMode(button_lightsoff, INPUT_PULLUP);
  pinMode(button_stop, INPUT_PULLUP);
  pinMode(button_aux, INPUT_PULLUP);
  pinMode(wheel, INPUT);

  
  // Initialize tft
  
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  tft.setCursor(0, 0, 2);
  tft.setTextColor(TFT_YELLOW, TFT_BLACK); // Note: the new fonts do not draw the background colour
  tft.print("OSRailway");

  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  tft.print("   Connecting.");

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  //tft.clear();
  tft.print("Connected!");
  
    // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    tft.print("Conn. failed!");
    while(1);
  }
}

void sendControlMessage(String command){
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    tft.print("Conn. failed!");
    while(1);
  }
  // We now create a URI for the request
  String url = command;
  url += streamId;
  url += "?private_key=";
  url += privateKey;
  url += "&value=";
  url += value;

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(50);
  
}

/*
void printSpeedBar(int value){
  int i = 0;
  int nrHighLights = 0;

  if(value > 0){
    nrHighLights = value / 8;
  }

  for(i = 0; i < 128; i++){
    if(i < nrHighLights){
      tft.printByte(0xFF, i, 0);
    } else {
      tft.printByte(0x00, i, 0);
    }
  }
}
*/

void loop() {
  int val;
  int motorSpeed;
  char * text;

  
  val = digitalRead(button_forward);
  if(val == 0){
    while(val == 0){
      val = digitalRead(button_forward);
    }
    motorSpeed = analogRead(wheel);
    isRunning = true;
    sendControlMessage("/run?dir=forward&speed=" + String(motorSpeed));
    tft.fillScreen(TFT_BLACK);
    tft.setCursor(0, 0, 2);
    tft.print("Motor ON forward");
  }

  val = digitalRead(button_reverse);
  if(val == 0){
    while(val == 0){
      val = digitalRead(button_reverse);
    }
    motorSpeed = analogRead(wheel);
    isRunning = true;
    sendControlMessage("/run?dir=backward&speed=" + String(motorSpeed));
    tft.fillScreen(TFT_BLACK);
    tft.setCursor(0, 0, 2);
    tft.print("Motor ON reverse");
  }

  val = digitalRead(button_stop);
  if(val == 0){
    while(val == 0){
      val = digitalRead(button_stop);
    }
    motorSpeed = 0;
    isRunning = false;
    sendControlMessage("/updateSpeed?speed=" + String(motorSpeed));
    tft.fillScreen(TFT_BLACK);
    tft.setCursor(0, 0, 2);
    tft.print("Motor OFF       ");
  }

  val = digitalRead(button_lightson);
  if(val == 0){
    while(val == 0){
      val = digitalRead(button_lightson);
    }
    sendControlMessage("/lighton?speed=" + String(motorSpeed));
    tft.fillScreen(TFT_BLACK);
    tft.setCursor(0, 0, 2);
    tft.print("Headlights ON ");
  }

  
  val = digitalRead(button_lightsoff);
  if(val == 0){
    while(val == 0){
      val = digitalRead(button_lightsoff);
    }
    sendControlMessage("/lightoff?speed=" + String(motorSpeed));
    tft.fillScreen(TFT_BLACK);
    tft.setCursor(0, 0, 2);
    tft.print("Headlights OFF");
  }
  
  if(isRunning){
    motorSpeed = analogRead(wheel);
    sendControlMessage("/updateSpeed?speed=" + String(motorSpeed));
  }

  delay(100);
}
Next I guess is adding wifi network picking and battery level reporting.

sidneylopsides
Posts: 12
Joined: Sun May 17, 2020 4:33 pm

Re: Modified remote - single board

Postby sidneylopsides » Mon May 18, 2020 6:36 pm

Ok it's all working but I've noticed you have to send the direction command whenever you change speed. So either need something that checks for changes and sends speed commands constantly, or maybe change theain controls to a rotary encoder where each click sends the change. Click can be stop.

Adding momentum would be cool too. Lots of reading to do!

admin
Site Admin
Posts: 284
Joined: Thu Jan 11, 2018 7:46 pm

Re: Modified remote - single board

Postby admin » Mon May 18, 2020 10:35 pm

Wow! that board looks really nice and for that price! :O I just ordered two of them right away! :D Thanks for bringing that one to my attention, that whole board costs less than just the display I used!

sidneylopsides
Posts: 12
Joined: Sun May 17, 2020 4:33 pm

Re: Modified remote - single board

Postby sidneylopsides » Tue May 19, 2020 8:08 am

I bought them a while backbecause they looked useful, but had no plan for them.
They are ideal for this remote control though, I'm working on a housing to print, I'll uploas that when it's ready.

Any ideas on a more "live" speed control? I'm guessing it's going to be case of constantly sending a speed command x number of times a second regardless of any control being touched.

As for simulated momentum, that seems like it would have to be something set in the locomotive code, but it does mean each train could have it's own feel.

admin
Site Admin
Posts: 284
Joined: Thu Jan 11, 2018 7:46 pm

Re: Modified remote - single board

Postby admin » Tue May 19, 2020 9:23 am

"bought them and had no plans for them", sounds like 99% of the stuff I buy. :lol:

I've been off this project for a couple of months, but now I'm working on it again. This time with a completely updated motorized bogie for an upcoming GP38 freight locomotive. I was totally determined to build a transmission that allows much bigger motors and that's a huge challenge given that I don't want to loose the multi-axis movement capability of the bogies. Attached is the current design I'm evaluating right now. Just to give you a little sneak peak as thanks for posting about this electronics! :) the GP38 will be released on Thingiverse.
Bogie.JPG
Bogie.JPG (66.53 KiB) Viewed 51 times
Regarding the wifi remote, there are tons of stuff that can be done there! I have so many ideas I can't even sort them in my head. :) A first thing I would investigate if you want to put some time into code is web socket. I have loosely started looking into that at work with the aim of also implement it on this system It is basically opening a data transfer channel rather than as of now using regular requests for each command that is sent. At the time when I programmed the current version I had many CAD-projects going on so I wanted something that worked reasonably good with minimum programming effort, and kind of hoped that someone else would pick up the torch and keep running so to speak. :)

I have been thinking about a more advanced remote. More like a layout control center where you can have buttons for several different trains, control switches and stuff, but it's not beyond idea stage. Initially when I programmed this I was thinking of making the control software computer based so a web page would act as GUI, but the reason I made the small remote was that my son could not at that time handle the iPad. He often pulled away the web page when trying to push the buttons, so therefor I built the remote so that he could play with this effortlessly.

It would be totally awesome if we could start a community effort to develop an open source firmware for both the trains and the control station, with multiple selectable options, and based on websocket.

Regarding individual train behaviour. A way of personalizing the trains behaviour is to have a lookup table with throttle values as well as individualized delay meaning for each control cycle the throttle value is only changing with X-amount (as long as you don't push emergency break). This can also be applied to lights that they dim with certain speeds.

admin
Site Admin
Posts: 284
Joined: Thu Jan 11, 2018 7:46 pm

Re: Modified remote - single board

Postby admin » Tue May 19, 2020 9:27 am

Another note, I will implement sensors down the line. First one I'm thinking of is inductive sensor that can read magnets placed in the track. That way the train could detect a station. Another thing is a light sensor that could probably pick up the difference created by running over the sleepers which could be summed up to calculate traveled distance. With the knowledge of the actual track layout, that would give a pretty solid position indication on the track.

sidneylopsides
Posts: 12
Joined: Sun May 17, 2020 4:33 pm

Re: Modified remote - single board

Postby sidneylopsides » Thu May 21, 2020 9:19 am

That bogie looks impressive. Is there any specific advantage to that gearing compared to having the motor vertical?

I only know very basic Arduino stuff so have been able to make adjustments, but no idea where to start with changing it further!

When I was searching I did come across a thread on rmweb forums where someone was making a wifi controlled locomotive system that was DCC compatible so he could still use standard DCC software etc.

admin
Site Admin
Posts: 284
Joined: Thu Jan 11, 2018 7:46 pm

Re: Modified remote - single board

Postby admin » Thu May 21, 2020 5:55 pm

There is no advantage just from an orientation standpoint, it is the combination with gear reduction and position of the motor that is the thing. I wanted to get in bigger motors and they are almost all wounded for too high rotation speeds so just direct drive will not work very well. With this design I can make motor mounts of varying shape to allow for example small brushless outrunners and DC-motors with different shape and sizes.

Programming is always about changing here and there and see what happens. :) That's the best way to learn! But of course I understand that going from that to large multi-node train control software is a bit of a stretch, but you shouldn't have much trouble at least adjusting the code for your trains. That's a good start to learn about the code.

sidneylopsides
Posts: 12
Joined: Sun May 17, 2020 4:33 pm

Re: Modified remote - single board

Postby sidneylopsides » Thu May 21, 2020 10:16 pm

Yeah I've already managed to do a little with changing for different motor drivers and the TTGO board.

This is the thread I saw about using and ESP8266 as a WiFi DCC decoder for o gauge.

https://www.rmweb.co.uk/community/index ... e-control/

admin
Site Admin
Posts: 284
Joined: Thu Jan 11, 2018 7:46 pm

Re: Modified remote - single board

Postby admin » Fri May 22, 2020 9:30 pm

Can't wait to get my TTGO-boards! :) I've decided to build a stand-alone control station with it. I will take a look at the code you posted in the other thread as well. My main idea is as follows:

Control unit is running a wifi access point on its ESP32 and the software in it registers each connecting IP as a train. I will have a couple of buttons with corresponding LED's to select which train to operate. When a train connects, the button lights up (or the LED right next to it) to show that it is online. I don't think it would be too hard to transmit the name of train also so that it can be displayed on the TFT. So you push the button for the train you want to control. Now the throttle is an interesting piece where there is several fun ideas, as the trains are probably in different throttle setting when you select them so if you have a physical throttle leaver that is at full throttle and you select a train at standstill, you don't want it to instantly accelerate. So either the throttle could be a digital encoder that spins "forever" with a wheel knob. One way is increase and the other is decrease throttle. That would be easy, but not so tactile. It would be really fun to have a very weak motor that changes the throttle leavers position when you select a train so that i corresponds to the active setting. :)

Also, it would be nice to have indicator LEd's for headlight settings and direction so when you select a train, you can see the active settings on the control panel.

For grownup nerds I think designing a fully computerized "ATC" would be cool, but I want to focus on kid-friendly projects and I see my 5 year old son often messing up the interface on the old smartphone he uses to control the trains so therefor I want to create a physical control station that is easy to use and "mechanical".

I would like as mentioned before to use web sockets instead of HTTP requests, so I'll see if that is not too hard to implement.

now a really neat thing to incorporate would be switches. I see the TTGO doesn't have that much I/O-connectivity, but there are servo multiplexer boards available so this control station could have cable connectors for switches where they are really just servo numbered servo outlets.

A thing i've struggled with and would really want to solve but it's a mechanical nightmare is to make the switches so that they allow pass-through from the "wrong" track if you see what I mean. Ironically it would be much easier to solve electronically with a servo-operated switch that could detect an incoming train preferably by a weight triggered button that the wheels press. It would either mean more wires from the switches to the control station, or each switch needs its own micro controller. I would like to avoid the latter to keep cost down. But 2 buttons would be enough because the incoming side doesn't need one, so +, -, servo, b1, b2 for each switch.

Including a sneak-peak at what I've been printing the last couple of days. :)
Attachments
IMG_1588.jpg
IMG_1588.jpg (189.53 KiB) Viewed 33 times


Who is online

Users browsing this forum: No registered users and 0 guests