Help required for m...
 
Notifications
Clear all

[Solved] Help required for model railway project

229 Posts
9 Users
12 Reactions
3,648 Views
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 4 years ago
Posts: 7632
 

@imillard Here are pictures of the 3 smallest (I may have one smaller but more expensive) they all have 8 GPIO minimum, 2 have WiFi on board the smallest needs an external antenna. If you need a better close up photo of any of them let me know.

Now for that 'beer' remark. This is a cultural difference, beer is beer, booze is rum, vodka, gin, etc. In the case of my coffee liquor, it is something like 1/2 the alcohol content though.

The smallest is an AI Thinker ESP-07S 16 pins external WiFi

The next is an ESP-12-E with 22 pins, a couple more GP and a SPI bus WiFi

The big one is 16 pins USB Mini WiFi ESP-12F, also known as Wemos D1 Mini

I also have an ESP-01 with WiFi on board very small but only 8 pins 2 GPIO, TX, RX, power + RST and EN - NOT recommended

I also have a SEEED XIO? but can't find it at the moment. Very small but pricy I think. You can goto the web site at HERE

 

IMG 8695
IMG 8694

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.


   
ReplyQuote
TFMcCarthy
(@tfmccarthy)
Member
Joined: 2 months ago
Posts: 129
 

@robotbuilder 

Posted by: @robotbuilder

Problem is getting the tutorial information to use two of these to make a bidirectional wireless peer to peer connection.

AFAIK, every ESP has WiFi built-in and is capable of using the ESP-NOW protocol. WiFi capability should not be an issue.

 


   
Ron reacted
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@bruceg 

Lucky you. I am probably 3 days away! I like to deal with people in person particularly if they are themselves into programming and electronics. There is an extra high cost with Australian suppliers but I don't really buy all that much stuff.

Waiting for you to post something about your projects apart from you posts about the MET project.

 


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

FYI @tfmccarthy  @zander @bruceg

And how are you going with setting up the Arduino IDE to compile esp32 code and installing the ESP-NOW library?

Below is the code I used to test that communication between the two boards was working.

You might think of it as template code to which you can add the behaviors you want.

It gives a random value to the int lock variable but of course that would be replaced with logic that uses sensor inputs to decide if to lock or unlock the drums.

The code is the same for both boards except the little message I send to identify the other board.  I called one the RED board and the other the GREEN board because the LED color each used. I guess MET1 and MET2 would be a better choice. Not that you would send a message in your actual application which will not be connected to a PC using the Serial Monitor.

#include <esp_now.h>
#include <WiFi.h>

// ====    MET INPUTS   ===
#include <ESP32Servo.h>
Servo lockServo;
int lockServoPin = 18;
#define BTN1  4
#define BTN2  0
#define LED1  2
// ===== ===================

//uint8_t broadcastAddress[] = {0x34, 0x98, 0x7A, 0xBC, 0xC8, 0x3C}; // red board
uint8_t broadcastAddress[] = {0x58, 0xBF, 0x25, 0x9F, 0x12, 0xF8}; // green board

// Define variables to store readings to be sent
int outgoingLock;
char outgoingMsg[32];

// Define variables to store incoming readings
int incomingLock;


// Variable to store if sending data was successful
String success;


typedef struct metData {
  char msg[32];
  int lock;
} metData;


// Create a metData to hold outgoing readings
metData outgoing;

// Create a metData to hold incoming readings
metData incoming;

esp_now_peer_info_t peerInfo;

// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&incoming, incomingData, sizeof(incoming));
  Serial.print("Bytes received: ");
  Serial.println(len);
  incomingLock = incoming.lock;
}
 
void setup() {
  // ======   MET SETUP =====
  pinMode(BTN1,INPUT_PULLUP); //configure pin as input with pullup enabled 
  pinMode(BTN2,INPUT_PULLUP);
  pinMode(LED1,OUTPUT);

  lockServo.attach(lockServoPin);
  lockServo.write(0);  // 0 to 170 degrees
  //==========================

  // Init Serial Monitor
  Serial.begin(115200);
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // 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 Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}
 
void loop() {

  outgoingLock = random(0,2);
  outgoing.lock = outgoingLock;
  strcpy(outgoing.msg, "Hello I am the RED Board!");

  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &outgoing, sizeof(outgoing));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }

  Serial.println(incoming.lock);
  Serial.println(incoming.msg);

  delay(10000);
}

 

SerialMonitorOutput

 

 

 

 


   
ReplyQuote
imillard
(@imillard)
Member
Joined: 2 months ago
Posts: 77
Topic starter  

Posted by: @robotbuilder

And how are you going with setting up the Arduino IDE to compile esp32 code and installing the ESP-NOW library?

Below is the code I used to test that communication between the two boards was working.

You might think of it as template code to which you can add the behaviors you want.

It gives a random value to the int lock variable but of course that would be replaced with logic that uses sensor inputs to decide if to lock or unlock the drums.

The code is the same for both boards except the little message I send to identify the other board.  I called one the RED board and the other the GREEN board because the LED color each used. I guess MET1 and MET2 would be a better choice. Not that you would send a message in your actual application which will not be connected to a PC using the Serial Monitor.

@robotbuilder

Hi John,

Still haven't had a chance to do much more on the project.  I hope to get back to it next week.

Cheers,

Ian

 

Ian Millard
Port Macquarie, NSW, Australia
ESP32/Arduino etc novice


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

I hope to get back to it next week.

No problem 🙂  Like I wrote earlier,  my interest in this is learning to use the esp32 and ESP-NOW.

I wondered what these parts of your machine did?

The parts I shaded pink, yellow and blue.

METO3

 


   
ReplyQuote
imillard
(@imillard)
Member
Joined: 2 months ago
Posts: 77
Topic starter  

Posted by: @robotbuilder

No problem 🙂  Like I wrote earlier,  my interest in this is learning to use the esp32 and ESP-NOW.

I wondered what these parts of your machine did?

The parts I shaded pink, yellow and blue.

-- attachment is not available --

 

@robotbuilder

Hi John,

The pink shaded area is a detent wheel attached to the main tumbler/drum to ensure the tumbler is always in the correct position ie with the slots for the staff at 12 o'clock, 3 o'clock, 6 o'clock & 9 o'clock.  The yellow part is a spring-loaded detent plunger housed in the blue part.

I hope that makes sense.

Cheers,

Ian

 

Ian Millard
Port Macquarie, NSW, Australia
ESP32/Arduino etc novice


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

Now we know that the ESP NOW protocol comes with the esp32 upgrade to the Arduino IDE there is no reason not to wire up some hardware and test some code when you are ready?

I have two push buttons, a LED and a servo motor to test drive as I showed earlier in these posts. Can add the other servo later. I understand you have a 30 pin esp32 board? I have the 38 pin esp32 board so I will have to select GPIO pins common to both. I notice the 30 pin board has nice oval shaped fat reset and boot buttons not so hard on the finger tips!

If you are trialing the self centering toggle switch then the center connection to ground and the others to their own pin set for output as BTN1 and BTN2 in my code.

 

 


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

This morning I edited the code to test with the hardware I have been using.

When you press one button on one board the servo motor on the other board will lock and when you press the other button the servo on the other board will unlock.

NOTE: You will need to change the pin connections for your board in the software and hardware.

And you will have to change the MAC codes.

Still work to be done but it is a start and appears to work ok so far.

The boards are being powered via the USB connections.

Interestingly I have seen esp32 servo examples using the 3.3v supply from the board.

 

Code for the RED board:

 

#include <esp_now.h>
#include <WiFi.h>

// ====    MET INPUTS   ===
#include <ESP32Servo.h>
Servo lockServo;
int lockServoPin = 18;  // GPIO 18
#define BTN1  4  // GPIO 4
#define BTN2  0  // GPIO 0
#define LED1  2  // GPIO 2

int locked = 0;  // state of lock

// ===== ===================

uint8_t broadcastAddress[] = {0x34, 0x98, 0x7A, 0xBC, 0xC8, 0x3C}; // grn board
//uint8_t broadcastAddress[] = {0x58, 0xBF, 0x25, 0x9F, 0x12, 0xF8}; // red board

// Variable to store if sending data was successful
String success;


typedef struct metData {
  char msg[32];
  int  command;  // 1 = lock, 2 = unlock
} metData;


// Create a metData to hold outgoing readings
metData outgoing;

// Create a metData to hold incoming readings
metData incoming;

esp_now_peer_info_t peerInfo;

// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&incoming, incomingData, sizeof(incoming));
  Serial.print("Bytes received: ");
  Serial.println(len);
}

 // DRUM FUNCTIONS 
void lockDrum(){
  if (locked == 0){
    lockServo.write(90);
    digitalWrite(LED1,HIGH);
    locked = 1;
  }
}

void unlockDrum(){
  if (locked == 1){
    lockServo.write(0);
    digitalWrite(LED1,LOW);
    locked = 0;
  }
}

 
void setup() {

  // ======   MET SETUP =====
  pinMode(BTN1,INPUT_PULLUP); //configure pin as input with pullup enabled 
  pinMode(BTN2,INPUT_PULLUP);
  pinMode(LED1,OUTPUT);

  lockServo.attach(lockServoPin);
  lockServo.write(0);  // 0 to 170 degrees
  //==========================

  // Init Serial Monitor
  Serial.begin(115200);
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // 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 Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}
 
void loop() {

  // *******  FILL outgoing struct with data to send **
 strcpy(outgoing.msg, "Hello I am the RED board");

  // ***********  FILL outgoing struct with data to send *****
  outgoing.command = 0;
  // send lock drum if BTN1 pressed
  if (digitalRead(BTN1) == LOW){
    outgoing.command = 1;
    strcpy(outgoing.msg, "LOCK DRUM");
  }

  // send unlock drum if BTN2 pressed
  if (digitalRead(BTN2) == LOW){
    outgoing.command = 2;
    strcpy(outgoing.msg,"UNLOCK DRUM");
  }


  // Send message via ESP-NOW
 
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &outgoing, sizeof(outgoing));
  // delay(50);
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }

  // display incoming data

  Serial.print("incoming message =");
  Serial.println(incoming.msg);
  Serial.print("incoming.command =");
  Serial.println(incoming.command);

  // act on incoming data

  if (incoming.command == 1){
    lockDrum();
    delay(500);
  }

  if (incoming.command == 2){
    unlockDrum();
    delay(500);
  }

  delay(50);
}

 

Code for the GREEN board:

#include <esp_now.h>
#include <WiFi.h>

// ====    MET INPUTS   ===
#include <ESP32Servo.h>
Servo lockServo;
int lockServoPin = 18;  // GPIO 18
#define BTN1  4  // GPIO 4
#define BTN2  0  // GPIO 0
#define LED1  2  // GPIO 2

int locked = 0;  // state of lock

// ===== ===================

//uint8_t broadcastAddress[] = {0x34, 0x98, 0x7A, 0xBC, 0xC8, 0x3C}; // grn board
uint8_t broadcastAddress[] = {0x58, 0xBF, 0x25, 0x9F, 0x12, 0xF8}; // red board

// Variable to store if sending data was successful
String success;


typedef struct metData {
  char msg[32];
  int  command;  // 1 = lock, 2 = unlock
} metData;


// Create a metData to hold outgoing readings
metData outgoing;

// Create a metData to hold incoming readings
metData incoming;

esp_now_peer_info_t peerInfo;

// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  if (status ==0){
    success = "Delivery Success :)";
  }
  else{
    success = "Delivery Fail :(";
  }
}

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&incoming, incomingData, sizeof(incoming));
  Serial.print("Bytes received: ");
  Serial.println(len);
}

 // DRUM FUNCTIONS 
void lockDrum(){
  if (locked == 0){
    lockServo.write(90);
    digitalWrite(LED1,HIGH);
    locked = 1;
  }
}

void unlockDrum(){
  if (locked == 1){
    lockServo.write(0);
    digitalWrite(LED1,LOW);
    locked = 0;
  }
}

 
void setup() {

  // ======   MET SETUP =====
  pinMode(BTN1,INPUT_PULLUP); //configure pin as input with pullup enabled 
  pinMode(BTN2,INPUT_PULLUP);
  pinMode(LED1,OUTPUT);

  lockServo.attach(lockServoPin);
  lockServo.write(0);  // 0 to 170 degrees
  //==========================

  // Init Serial Monitor
  Serial.begin(115200);
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // 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 Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}
 
void loop() {

  // *******  FILL outgoing struct with data to send **
 strcpy(outgoing.msg, "Hello I am the GREEN board");

  // ***********  FILL outgoing struct with data to send *****
  outgoing.command = 0;
  // send lock drum if BTN1 pressed
  if (digitalRead(BTN1) == LOW){
    outgoing.command = 1;
    strcpy(outgoing.msg, "LOCK DRUM");
  }

  // send unlock drum if BTN2 pressed
  if (digitalRead(BTN2) == LOW){
    outgoing.command = 2;
    strcpy(outgoing.msg,"UNLOCK DRUM");
  }


  // Send message via ESP-NOW
 
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &outgoing, sizeof(outgoing));
  // delay(50);
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }

  // display incoming data

  Serial.print("incoming message =");
  Serial.println(incoming.msg);
  Serial.print("incoming.command =");
  Serial.println(incoming.command);

  // act on incoming data

  if (incoming.command == 1){
    lockDrum();
    delay(500);
  }

  if (incoming.command == 2){
    unlockDrum();
    delay(500);
  }

  delay(50);
}

 

esp32Boards

 

 

 

 

 

 


   
ReplyQuote
imillard
(@imillard)
Member
Joined: 2 months ago
Posts: 77
Topic starter  

Posted by: @robotbuilder

This morning I edited the code to test with the hardware I have been using.

When you press one button on one board the servo motor on the other board will lock and when you press the other button the servo on the other board will unlock.

NOTE: You will need to change the pin connections for your board in the software and hardware.

And you will have to change the MAC codes.

Still work to be done but it is a start and appears to work ok so far.

The boards are being powered via the USB connections.

Interestingly I have seen esp32 servo examples using the 3.3v supply from the board.

@robotbuilder

Hi John,

That sounds great.  I'll see if I can hook things up and trial it.

Not sure if I'm jumping the gun here, but remember that both machines' drums need to be locked simultaneously, when the switch in one machine is triggered for staff removal (eg the GREEN board).  Same on the reverse.  When the switch on the RED board is triggered (to detect insertion of the staff), both drum servos need to be unlocked. 

Forgive my ignorance if that's what your code does.

Also, referring to the pin layout for my board, would I be correct in saying that I can use the same pin connections as you have?

image

Cheers,

Ian

 

Ian Millard
Port Macquarie, NSW, Australia
ESP32/Arduino etc novice


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

No I haven't inserted the lines to lock and unlock the drum of the sender at the same time, YET.  This is why I wrote,

Still work to be done but it is a start and appears to work ok so far.

I guess the sender locking and unlocking itself at the same time would go in this section.

// *********** FILL outgoing struct with data to send *****
outgoing.command = 0;
// send lock drum if BTN1 pressed
if (digitalRead(BTN1) == LOW){
outgoing.command = 1;
strcpy(outgoing.msg, "LOCK DRUM");
lockDrum(); ////////////////////////////// HERE
}

// send unlock drum if BTN2 pressed
if (digitalRead(BTN2) == LOW){
outgoing.command = 2;
strcpy(outgoing.msg,"UNLOCK DRUM");
unlockDrum(); //////////////////////////// AND HERE
}

 

There are a number of issues that I wanted to think about including dealing with a message not getting through that is why you get a Success or Failure signal and have to deal with such errors. There may also be timing errors. The delay() may not be the best solution although it works here. I have to think about it some more.

I ran out of time this morning will look and at it again, and test it, later.

As far as I know the GPIO numbers are the same but the actual physical layout of the pins on the board attached to those GPIO numbers can be different.

This is my esp32 board pin layout.

ESP32 38Pin

 


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

Hi Ian,

So if I attach something to the GPIO2 label on my board it is to pin 24 and if you attach something to the GPIO2 label on your board it is pin 2.

At least as I understand it looking at the images.

Cheers John

 


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

It is probably worth while learning about the pinouts and what to keep in mind in selecting a pin.
For example:
"For ESP32 DEVKIT V1 board, GPIO6 to GPIO11 are connected to the integrated SPI flash and are not recommended for other uses."

This seems to be the ESP32 Pinout Reference for the board you are using.

https://lastminuteengineers.com/esp32-pinout-reference/

More pinout knowledge.

https://randomnerdtutorials.com/esp8266-pinout-reference-gpios/

I will need to make a hard copy for future reference.


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 4 years ago
Posts: 7632
 

@robotbuilder fyi @imillard I just wanted to tell you I do lots of little experiments with esp32 devices all the time and I grab a random board with anywhere from about 30 to 38 pins. All I ever do is connect to the GPIO number, it doesn't matter what the physical pin is. I even have the special breadboard Bill told us about to handle the wide esp32 boards. I recently added a few of the new S3 boards, hopefully this winter I will experiment with them as well. I doubt there will be any problems other than the documented V3 library issues which I know how to deal with. A GPIO pin with a given number is the same no matter the version, number of total pins form factor etc. Those with more pins have added functionality and obviously there are some backward compatibility issues but they are obvious.

Yes there are some special cases but I find the NERDS pinout diagram warns me away from those few.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2171
 

@imillard 

I noted that your board does not have a GPIO 0 pin so maybe I will change the code,
#define BTN1 4
#define BTN2 2
#define LED1 16
And rewire the board accordingly.

esp32TouchSwitch

I made the edit I suggested above and now both servo motors open/close from pressing buttons on either board.

Out of curiosity I changed the code to test the capacitive touch input option and it worked.

https://dronebotworkshop.com/esp32-intro/

touchSwitch

Getting close to a working solution?  Just have to add that other servo and its logic.

 

 

 


   
ReplyQuote
Page 13 / 16