Железная дорога на Arduino

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
Всем привет! Имеется несколько комплектов ЖД Fenfa. Масштаб 1/87, рельсы - пластик, локомотивы на батарейках (2шт. АА),
в общем обычная, но не самая дешманская железная дорога. Замечательно то, что рельсы можно покупать отдельно и построить ЖД любых размеров.

Задача: Перевести всё в автоматический режим, а также управление вручную со смартфона.
Прикинул схему для начинки поезда:
  • В локомотивы вместо штатных батареек - 1 банка Li-ion/Li-Po + модуль зарядки TP4056 USB
  • Повышающий преобразователь напряжения SX1308 2-28V 2A
- Драйвер двигателя типа mini L298N
- ESP-32 (у меня они есть)
- Модуль датчика освещенности на фоторезисторе (установка - днище поезда, фоторезистор смотрит на рельсы)
- Датчик препятствия (модуль YL-63) (установка - в нос поезда, чтобы избежать столкновения с другими поездами)
- Сенсорная кнопка TTP223 (триггер, один клик - поезд едет вперед, второй клик - стоп)

Схема ЖД путей (см. рисунок):
На рисунке указаны метки:
- Красные - это датчики препятствия типа KY-033
- Зеленые - это светодиоды
- На каждой стрелке будет установлено по одной сервомашинке типа SG90
- ESP-32
ЖД.PNG


Алгоритм движения. Имеется (пока что) два поезда, идущие на встречу друг другу, когда один из поездов наезжает на Красную метку - включаются светодидоды (зеленые метки),
встроенные в рельсы, фоторезистор Второго поезда фиксирует сигнал светодиода и даёт команду остановить поезд до тех пор, пока не переведутся стрелки и не проедет Первый
поезд. Сервами, датчиками и светодиодами на рельсах будет управлять ESP-32.

На этом я затупил и что делать дальше не соображу. В написании кода не силён, залить скетч в Arduino IDE проблем нет, много девайсов собрал. Сейчас изучаю FLProg, Blynk и думаю,
что для идентификации поездов можно создать сеть из ESP-32. ESP32 на рельсах - Точка доступа, ESP32 на поездах - клиенты. Плюсом ESP-32 есть наличие Bluetooth, для управления
со смартфона (Приложение RemoteXY и т.д.). Здесь я тоже не понял, можно ли управлять и через WiFi, и через Bluetooth одновременно? И надо ли вообще?

Если у кого-то есть какие пожелания, советы, буду очень благодарен. Ткните носом куда копать. Надеюсь продолжение следует:)
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,272
1,303
Москва
Кнопка на поезде зачем , если упрвление через смартфон ?
Рекомендую глянуть , может поможет, есть что то общее:

ВиФи и блютус да, могут работать одновременно. надо ли? не знаю.
я себе плохо представляю что можно делать. Начал бы с управления стрелками и создания семафоров. Но мне это не интересно.. все корона проклятая, убила все интересы :D
 

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
@Старик Похабыч, Спасибо, видео посмотрю. Кнопка это на случай, если не будет смартфона рядом.

@bort707, Спасибо, это я давно уже понял)

@bort707, А что скажете по поводу MicroPython?
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,975
634
45
Язык программирования это только инструмент. Подавляющее большинство в программе - это логика работы, а логику особо пофигу на каком языке писать.
Так что пишите на том языке на каком легче и который лучше всего знаете.
 

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
@Геннадий П, Спасибо. Я поэтому сейчас вникаю в Flprog, там уже есть готовые блоки, платы, модули и как всё работает, заливаю в плату через Arduino IDE и походу код просматриваю. Понимаю, что лучше с нуля всё начинать.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,975
634
45
@mcvall, Визуальное программирование вполне себе отличное начало.
Можешь еще Flowcode посмотреть. Сам иногда в нем небольшие наброски делаю, когда нужно по-быстрому что нть простое сделать.
 

bort707

★★★★★★✩
21 Сен 2020
3,067
915
Я сейчас вникаю в Flprog, там уже есть готовые блоки, платы, модули и как всё работает, заливаю в плату через Arduino IDE и походу код просматриваю.
вот тут не соглашусь с @Геннадий П, и посоветую не тратить время на визуальные среды типа Flprog . Вы очень быстро столкнетесь с их ограниченностью и отсутсвием поддержки.
А "просмотр кода" FLProg вряд ли чему хорошему вас сможет научить...
 
Изменено:
  • Лойс +1
Реакции: Nikanor и PiratFox

Arhat109

★★★★✩✩✩
9 Июн 2019
473
203
Замечательно то, что рельсы можно покупать отдельно и построить ЖД любых размеров
Поделитесь ссылкой, где рельсы можно докупать отдельно, а то пришлось в свое время делать стрелки (2х4шт простых стрелки и одну английскую) самостоятельно, впрочем как и рельсы иных размеров.. :( У fenfa помнится колея была 20мм, из-за чего стандартные германские рельсы не подходили никак..

Из визуальщины могу порекомендовать Ardublock, но не знаю насколько он сейчас поддерживается.
 

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
@Arhat109, Я в Украине живу. На сайте ОЛХ парень продаёт, но сейчас нету в наличии стрелок и прямых. Где он их берёт я не знаю:)
По поводу визуальщины - оставил я её, начал С/С++ изучать.
 
  • Лойс +1
Реакции: Nikanor и Arhat109

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
@Arhat109, Можно ведь купить ещё один набор, не намного дороже получается.
 

Arhat109

★★★★✩✩✩
9 Июн 2019
473
203
В наборах нет стрелок, от слова совсем. Ну или не было в 2010-2012гг когда брались мои наборы сыну. Ну и рельсы у них только R4, пришлось делать R3, для некоторых построюшек. Меня хватило только на 1 круг, и то..
К сожалению, фото стрелок не сохранилось. Английская стрелка ещё не крашенная. На первом - элемент моста и рельса R3. На последнем R3 отдельно. Так было раскрашено 2 полных круга штатных R4 и стрельки. Но это уже существенно позже этих фото.

К сожалению, ведущие колеса локомотивов у них очень хлипкие, ремонтировались по нескольку раз..
IMG_1207.JPGDSCN2081.JPGDSCN1508.JPGDSCN2071.JPG100_0348.JPG
 
  • Лойс +1
Реакции: mcvall

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
В наборах нет стрелок, от слова совсем.
Сейчас рельсы идут без подложки как у Вас и стрелок Х-образных тоже нет, только радиус и прямо. Я купил два почти одинаковых набора в максимальной комплектации по 30 у.е. каждый, там в каждом по 4 стрелки идёт.
 
  • Лойс +1
Реакции: Arhat109

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
Ребята, может кто встречал библиотеку для управления DC мотором для ESP32? У Гайвера есть отличная GyverMotor, но она не подходит. Вообще управление ШИМом на ESP32 по другому реализовано. Или я много чего не знаю?:)

Набросал схему начинки поезда, т.к. в библиотеке Fritzing нет драйвера MX1508, я использовал L298N. Естественно всё будет подключаться соответственно даташиту MX1508.
 

Вложения

Изменено:

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
Всем привет. Прошу помочь настроить управление скоростью двигателя на драйвере MX1508 и ESP32. В первом скетче я научил его включать и отключать двигатель. Во втором скетче он тоже включается выключается с кнопки, я настроил PWM, но не пойму как управлять скоростью. Мне нужно, чтобы двигатель набирал обороты постепенно к определенному значению (допустим 100 из 0-255) и так же в обратном. Перелопатил интернет, для ESP32 везде используют драйвер L298N, в котором есть ещё 3-й пин EN для управления скоростью, в отличии от MX1508, в котором всего два.


// Управление двигателем Без PWM
const int motor1Pin1 = 5;
const int motor1Pin2 = 18;
const int buttonPin = 22;
int buttonState = 0;


void setup() {
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(buttonPin, INPUT);
}

void loop() {
// считываем значение кнопки:
buttonState = digitalRead(buttonPin);
// Двигатель "Вперед"
if (buttonState == HIGH) {
digitalWrite(motor1Pin1, LOW); //Если кнопка нажата, Двигатель "Вперед"
digitalWrite(motor1Pin2, HIGH);
} else {
// Двигатель "Стоп":
digitalWrite(motor1Pin1, LOW); //Если кнопка НЕ нажата, Двигатель "Стоп"
digitalWrite(motor1Pin2, LOW);
}
}
// Управление двигателем PWM
const int motor1Pin1 = 5;
const int motor1Pin2 = 18;
const int buttonPin = 22;

int buttonState = 0;

// задаем свойства ШИМ-сигнала:
const int freq = 5000;
const int ledChannel = 22; // или (pwmChannel)
const int resolution = 8;
int dutyCycle = 255;

void setup() {
// настраиваем ШИМ-сигнал согласно свойствам, заданным выше:
ledcSetup(ledChannel, freq, resolution);

// Указываем, что пины работают на выход:
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(buttonPin, INPUT);

// привязываем канал к двум GPIO-контактам:
ledcAttachPin(motor1Pin1, ledChannel);
ledcAttachPin(motor1Pin2, ledChannel);
}

void loop(){
buttonState = digitalRead(buttonPin);

// Двигатель "Вперед"
if (buttonState == HIGH) {
digitalWrite(motor1Pin1, LOW); //Если кнопка нажата, Двигатель "Вперед"
digitalWrite(motor1Pin2, HIGH);
ledcWrite(ledChannel, dutyCycle);
} else {
// Двигатель "Стоп":
digitalWrite(motor1Pin1, LOW); //Если кнопка НЕ нажата, Двигатель "Стоп"
digitalWrite(motor1Pin2, LOW);
ledcWrite(ledChannel, dutyCycle);
}
}

Схема управления двигателем:
 

Вложения

Старик Похабыч

★★★★★★★
14 Авг 2019
4,272
1,303
Москва
При движении вперед IN2 будет LOW, IN1 надо PWM. Но со временем PWM надо изменять.
будет что то такое:
#define максимальноеPWM=120;
текущееPWM=0;

loop{
...
Если (двигаемся вперед)
{
если (текущееPWM<максимальноеPWM)
{
если прошел какой то небольшой отрезок времени, то увеличить текущееPWM на 1.
}
...
}

И еще надо учесть , что при движении в обратную сторону стоп будет при PWM 255, а максимальная скорость при 0.
 
  • Лойс +1
Реакции: mcvall

Arhat109

★★★★✩✩✩
9 Июн 2019
473
203
Либо подключать 4 PWM ноги на один драйвер, что как-бы "жырно". Мутный драйвер, и слаботочный. Эти желтые моторы в ряде случаев могут его и пожечь с его 1.5А, маловато, однако.
 

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
#define максимальноеPWM=120;
текущееPWM=0;
Приветствую. Чтобы управлять ШИМ, в функции loop я создал локальную переменную int dutyCycle со значением 0. Также я создал цикл while, чтобы мотор стартовал и плавно набирал обороты до значения 100, но теперь я не могу выйти из цикла, пробовал оператором break, но не помогло. Мне нужно выполнить условие в цикле один раз и остановиться на значении 100, чтобы мотор продолжал вращение до следующей команды. Может лучше через какой-нибудь таймер с millis это все организовать?
// Управление двигателем PWM2
const int motor1Pin1 = 5; // номер контакта для IN1 драйвера двигателя
const int motor1Pin2 = 18; // номер контакта для IN2 драйвера двигателя
const int buttonPin = 22; // номер контакта для кнопки
int buttonState = 0; // переменная для хранения статуса кнопки:

// задаем свойства ШИМ-сигнала:
const int freq = 5000; // Частота
const int ledChannel = 0; // Канал,генерирующий PWM-сигнал для motor1Pin2
const int ledChannel_1 = 1;// Канал,генерирующий PWM-сигнал для motor1Pin1
const int resolution = 8; // Разрешение


void setup() {
ledcSetup(ledChannel, freq, resolution); // настраиваем ШИМ-сигнал согласно свойствам, заданным выше
ledcSetup(ledChannel_1, freq, resolution);

pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(buttonPin, INPUT);

ledcAttachPin(motor1Pin1, ledChannel_1); // где: motor1Pin1 - контакт для вывода PWM, ledChannel - канал,генерирующий PWM-сигнал для motor1Pin1
ledcAttachPin(motor1Pin2, ledChannel);
}

void loop(){
buttonState = digitalRead(buttonPin); // считываем значение кнопки:

if (buttonState == HIGH) { // если нажата, значением в «buttonState» будет «HIGH»:
int dutyCycle = 0;
int dutyCycle_1 = 0;

while (dutyCycle <= 0, dutyCycle_1 <= 100){
ledcWrite(ledChannel_1, dutyCycle_1); // ledChannel - генерирующий PWM, dutyCycle - коэффициент заполнения PWM-сигнала
ledcWrite(ledChannel, dutyCycle);
//dutyCycle = dutyCycle + 5;
dutyCycle_1 = dutyCycle_1 + 5;
delay(500);
}

} if (buttonState != HIGH) { //Кнопка выкл.
int dutyCycle = 0;
int dutyCycle_1 = 0;
ledcWrite(ledChannel_1, dutyCycle_1);
ledcWrite(ledChannel, dutyCycle);
}
}
// Управление двигателем PWM2
const int motor1Pin1 = 5;
const int motor1Pin2 = 18;
const int buttonPin = 22;
int buttonState = 0;


const int freq = 5000; // Частота
const int ledChannel = 0;
const int ledChannel_1 = 1;
const int resolution = 8;


void setup() {
ledcSetup(ledChannel, freq, resolution);
ledcSetup(ledChannel_1, freq, resolution);

pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(buttonPin, INPUT);

ledcAttachPin(motor1Pin1, ledChannel_1);
ledcAttachPin(motor1Pin2, ledChannel);
}

void loop(){

buttonState = digitalRead(buttonPin);
// Мотор "Вперёд"
if (buttonState == HIGH) {
int dutyCycle = 0;
int dutyCycle_1 = 0;

while (dutyCycle <= 0, dutyCycle_1 <= 100){
ledcWrite(ledChannel_1, dutyCycle_1);
ledcWrite(ledChannel, dutyCycle);
dutyCycle_1 = dutyCycle_1 + 5;
delay(500);
}
// Мотор "Стоп"
} if (buttonState != HIGH) {
int dutyCycle = 0;
int dutyCycle_1 = 0;
ledcWrite(ledChannel_1, dutyCycle_1);
ledcWrite(ledChannel, dutyCycle);
}
}
 
Изменено:

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
Либо подключать 4 PWM ноги на один драйвер, что как-бы "жырно". Мутный драйвер, и слаботочный. Эти желтые моторы в ряде случаев могут его и пожечь с его 1.5А, маловато, однако.
Мотор у меня один, по паспорту они жрут 400мА, драйвер в пике держит 2,5А. Думаю хватит, если нет, куплю сильнее:)
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,272
1,303
Москва
@mcvall,
Код лучше оформить в виде кода (есть соотв тег)
Надо вам почитать про цикл While
В моем алгоритме плавный разгон и торможение будут присутствовать и без цикла while.
По большому счету надо вычислять единичное значение для изменения текущего цикла к тому,что надо.
Пример
если нужная скважность не равна тому что сейчас, то:
если прошел нужный интервал времени, то
Нужна скважность 80%, сейчас есть 34%
Получаем изменение (80-34)/abs(80-34)=1
Нужна скважность 80%, сейчас есть 94%
Получаем изменение (80-94)/abs(80-94)=-1
скважность сейчас = скважность сейчас + полученное изменение
запомнить время.

При этом не надо считать в процентах, надо помнить , что 100% это будет 255 и все.
И еще меня интервал времени будет меняться ускорение .

Это все вот так и вставляется в цикл loop
Дополнительно в нем надо получать нужное значение скважности. Если это кнопка, то будет просто 255 или 0 в зависимости от ее состояния. При этом можно использовать вторую кнопку для экстренного торможения, меняя от ее состояния временной интервал.
Если еще подключить энкодер, то им можно выставлять скважность, а 1-ая кнопка будет полный газ или его отсутствие. Можно даже нажав кнопку медленнее разгонять поезд энкодером.
 
  • Лойс +1
Реакции: mcvall

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
В моем алгоритме плавный разгон и торможение будут присутствовать и без цикла while.
Спасибо, энкодер пока не нужен. Сейчас хочу сделать только автоматическое управление без смартфона. Нажал кнопку - поехал, нажал второй раз - остановка.

Если еще подключить энкодер, то им можно выставлять скважность, а 1-ая кнопка будет полный газ или его отсутствие. Можно даже нажав кнопку медленнее разгонять поезд энкодером
Я только сейчас догнал, вы имели ввиду программный энкодер?
 

mcvall

✩✩✩✩✩✩✩
15 Ноя 2020
33
3
нет, аппаратный, как внешнее устройство. Или даже потенциометр обыкновенный.
Понял. Сделал я ускорение и постепенное торможение через deley, но теперь ведь deley будет тормозить все процессы, опросы датчиков. Короче сижу курю таймеры на millis. Как всё запутано в этом программировании, не хватает мне знаний пока:)