Автор Тема: ARDUINO на замену КИРПИЧУ  (Прочитано 8041 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Alexandro

  • Ветеран
  • *****
  • Сообщений: 531
  • Репутация: +21/-3
  • zené vonat
  • Откуда: SPb
  • Имя: Alexander
Re: ARDUINO на замену КИРПИЧУ
« Ответ #45 : 12 Марта 2017, 13:50:50 »
теперь разобрался, спс!
частота таймера в void setup ставится ?
скетч под энкодер не пришлете заодно?
стоит ли инерцию двигателя изображать программно ?
DR/DB/FS/MAV

Оффлайн BNSF9399

  • Ветеран
  • *****
  • Сообщений: 1272
  • Репутация: +116/-1
  • Откуда: Москва
  • Имя: Владимир
Re: ARDUINO на замену КИРПИЧУ
« Ответ #46 : 12 Марта 2017, 18:00:15 »

скетч под энкодер не пришлете заодно?
Энкодер по хорошему через прерывания нужно делать. Но у UNO только два прерывания на входах D2 и D3, а D3 моторшилд использует под ШИМ.
Можно, конечно, на второй мост переделать, тогда и с прерываниями можно намутить.
Если питать все от 12 вольт, то как есть. Если питание рельс больше 12 вольт, то на моторшилде нужно перерезать перемычку Vin



Оба файла положить в папку dc
dc_config.h
#define TRACK_POWER_PIN 3 // PWM выход сигнала
#define TRACK_DIR_PIN 12 // вход направления движения
#define TRACK_AMP_PIN A0 // вход контроля тока
#define TRACK_MAX_AMP 700 // максимальное значение на выходе контроля тока (0-1024)
#define ENCODER_BUTTON_PIN 2 // вход кнопки энкодера
#define ENCODER_A_PIN 4 // вход сигнала энкодера А
#define ENCODER_B_PIN 5 // вход сигнала энкодера Б
#define DIRECTION_SWTCH_PIN 7 // вход переключателя направления движения
#define POWER_BUTTON_PIN 10 // вход кнопки включения/выключения
#define POWER_LED_PIN 6 // выход светодиода индикации включения питания
#define START_ENCODER_POS 3 // значение энкодера для положения 1 ("стартовое напряжение", 1-24)

dc.ino
#include "dc_config.h"
#include <Bounce2.h>

unsigned char encA; // состояние энкодера А
unsigned char encB; // состояние энкодера Б
unsigned char lastA = 0; // последнее состояние энкодера А
int FwdRev = 0; // направление вращения энкодера: 0 против часовой, 1 по часовой
int encoderPos = 0; // текушее положение энкодера
int scaled = 0; // значение положения энкодера приведенное в диапазон 0-255 для PWM
byte trackPWR = 0; // питание рельс: 0-выключено, 1 включено

unsigned long currentTime; // текущее время
unsigned long loopTime; // пследнее время выполнения цикла считывания состояния энкодера
int dir = 0; // направление движения: 0 вперед, 1 назад

Bounce pwrBouncer;
Bounce encBouncer;
Bounce dirBouncer;

void setup() {
  TCCR2B = TCCR2B & B11111000 | B00000110;
  pinMode(ENCODER_A_PIN, INPUT);
  pinMode(ENCODER_B_PIN, INPUT);
  pinMode(DIRECTION_SWTCH_PIN, INPUT);
  pinMode(POWER_BUTTON_PIN, INPUT);
  pinMode(TRACK_POWER_PIN, OUTPUT);
  pinMode(TRACK_DIR_PIN, OUTPUT);
  pinMode(POWER_LED_PIN, OUTPUT);
  currentTime = millis();
  loopTime = currentTime;
  digitalWrite(TRACK_POWER_PIN, LOW);
  digitalWrite(TRACK_DIR_PIN, LOW);
  pwrBouncer = Bounce();
  pwrBouncer.attach(POWER_BUTTON_PIN);
  pwrBouncer.interval(5);
  encBouncer = Bounce();
  encBouncer.attach(ENCODER_BUTTON_PIN);
  encBouncer.interval(5);
  dirBouncer = Bounce();
  dirBouncer.attach(DIRECTION_SWTCH_PIN);
  dirBouncer.interval(5);
}

void loop() {
  currentTime = millis();
  if(encBouncer.update()){
    if(encBouncer.read() == LOW){
      digitalWrite(TRACK_POWER_PIN, LOW);
      encoderPos = 0;
    }
  }
  if(pwrBouncer.update()){
    if(pwrBouncer.read() == LOW){
      trackPWR = !trackPWR;
      digitalWrite(POWER_LED_PIN, trackPWR);
    }
  }
  if(dirBouncer.update()){
    dir = dirBouncer.read();
    digitalWrite(TRACK_DIR_PIN,dir);
  }
  if (analogRead(TRACK_AMP_PIN) > TRACK_MAX_AMP) {
    trackPWR = 0;
    digitalWrite(TRACK_POWER_PIN, LOW);
    digitalWrite(POWER_LED_PIN, LOW);
  }

  if(trackPWR){
    if(currentTime >= (loopTime + 5)){
      encA = digitalRead(ENCODER_A_PIN);
      encB = digitalRead(ENCODER_B_PIN);
      if((!encA) && (lastA)){
        if(encB) {
          if (encoderPos <= 24) {
            encoderPos ++;
            if(encoderPos < START_ENCODER_POS) encoderPos = START_ENCODER_POS;
          }
          FwdRev = 1;
        }
        else {
          if(encoderPos >= START_ENCODER_POS){
            encoderPos --;
            if(encoderPos < START_ENCODER_POS) encoderPos = 0;
          }
          FwdRev = 0;
        }
      }
      lastA = encA;
      scaled = encoderPos * 10;
      loopTime = currentTime;
    }
    analogWrite(TRACK_POWER_PIN, scaled);
  }
}

Оффлайн gidra

  • Постоялец
  • ***
  • Сообщений: 167
  • Репутация: +23/-0
  • Откуда: Пермь
Re: ARDUINO на замену КИРПИЧУ
« Ответ #47 : 12 Марта 2017, 21:38:06 »
Поэтому, не парьтесь, а ставьте минимальную частоту и будет вам счастье.
То есть производители DCC- декодеров возможность работы на частоте шим в 40 кГц по своей дурости делают?

Оффлайн Gematogen

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 6923
  • Репутация: +252/-1
  • Имя: Михаил
Re: ARDUINO на замену КИРПИЧУ
« Ответ #48 : 12 Марта 2017, 22:10:22 »
Я чаще всего встречал 20 кГц.
Если ниже, то это уже в звуковом диапазоне. Что удивляться писку?
Михаил, DCC

Оффлайн BNSF9399

  • Ветеран
  • *****
  • Сообщений: 1272
  • Репутация: +116/-1
  • Откуда: Москва
  • Имя: Владимир
Re: ARDUINO на замену КИРПИЧУ
« Ответ #49 : 12 Марта 2017, 22:22:57 »
То есть производители DCC
тему читали? какое отношение она к DCC имеет?

... и добавил:
Что удивляться писку?
Миша, от тебя я такого не ожидал :)
Ради интереса, возьми и попробуй раскрутить движок постоянного тока от 40кГц со скважностью хотябы 5%

Оффлайн Gematogen

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 6923
  • Репутация: +252/-1
  • Имя: Михаил
Re: ARDUINO на замену КИРПИЧУ
« Ответ #50 : 12 Марта 2017, 23:46:43 »
Ради интереса, возьми и попробуй
Как? :-[
попробуй раскрутить движок постоянного тока от 40кГц со скважностью хотябы 5%
А что, не раскрутится?
Я со всякими индукциями не силён.
Но, КМК DCC работает на 20 кГц.
Михаил, DCC

Оффлайн BNSF9399

  • Ветеран
  • *****
  • Сообщений: 1272
  • Репутация: +116/-1
  • Откуда: Москва
  • Имя: Владимир
Re: ARDUINO на замену КИРПИЧУ
« Ответ #51 : 12 Марта 2017, 23:53:27 »
Покрутил-повертел-подумал...
А есть ли смысл ШИМ гонять от нуля до 255?
Замеры показали следующий результат. При максимальной частоте 31372.55 Гц Като трогается при значении 130 (51%),Атлас 160 (62%)
Ни рыка, ни писка естественно нет.
Перепилил скетч
Добавил дебаг. Для включения расскоментить последнюю строку в конфиге
Добавил переменные
START_DUTY_CYCLE - стартовое значение скважности (вместо START_ENCODER_POS)
SPEED_STEP - количество шагов энкодера от нуля до максимума
сдвиг скважности ШИМ на шаг энкодера рассчитывается как (255-START_DUTY_CYCLE)/SPEED_STEP

dc_config.h
#define TRACK_POWER_PIN 3 // PWM выход сигнала
#define TRACK_DIR_PIN 12 // вход направления движения
#define TRACK_AMP_PIN A0 // вход контроля тока
#define TRACK_MAX_AMP 700 // максимальное значение на выходе контроля тока (0-1024)
#define ENCODER_BUTTON_PIN 2 // вход кнопки энкодера
#define ENCODER_A_PIN 4 // вход сигнала энкодера А
#define ENCODER_B_PIN 5 // вход сигнала энкодера Б
#define DIRECTION_SWTCH_PIN 7 // вход переключателя направления движения
#define POWER_BUTTON_PIN 10 // вход кнопки включения/выключения
#define POWER_LED_PIN 6 // выход светодиода индикации включения питания
#define START_DUTY_CYCLE 127 // минимальное значение скважности ШИМ
#define SPEED_STEP 28 // количество шагов энкодера
#define Debug Serial
#define DebugBaud 115200
//#define DEBUG

dc.ino
#include "dc_config.h"
#include <Bounce2.h>

unsigned char encA; // состояние энкодера А
unsigned char encB; // состояние энкодера Б
unsigned char lastA = 0; // последнее состояние энкодера А
int FwdRev = 0; // направление вращения энкодера: 0 против часовой, 1 по часовой
int encoderPos = 0; // текушее положение энкодера
int scaled = 0; // значение положения энкодера приведенное в диапазон 0-255 для PWM
byte trackPWR = 0; // питание рельс: 0-выключено, 1 включено

unsigned long currentTime; // текущее время
unsigned long loopTime; // пследнее время выполнения цикла считывания состояния энкодера
int dir = 0; // направление движения: 0 вперед, 1 назад
float scale_step = (255 - START_DUTY_CYCLE) / SPEED_STEP;

Bounce pwrBouncer;
Bounce encBouncer;
Bounce dirBouncer;

void setup() {
  #if defined(DEBUG)
    Debug.begin(DebugBaud);
  #endif
  TCCR2B = TCCR2B & B11111000 | B00000001;
  pinMode(ENCODER_A_PIN, INPUT);
  pinMode(ENCODER_B_PIN, INPUT);
  pinMode(DIRECTION_SWTCH_PIN, INPUT);
  pinMode(POWER_BUTTON_PIN, INPUT);
  pinMode(TRACK_POWER_PIN, OUTPUT);
  pinMode(TRACK_DIR_PIN, OUTPUT);
  pinMode(POWER_LED_PIN, OUTPUT);
  currentTime = millis();
  loopTime = currentTime;
  digitalWrite(TRACK_POWER_PIN, LOW);
  digitalWrite(TRACK_DIR_PIN, LOW);
  pwrBouncer = Bounce();
  pwrBouncer.attach(POWER_BUTTON_PIN);
  pwrBouncer.interval(5);
  encBouncer = Bounce();
  encBouncer.attach(ENCODER_BUTTON_PIN);
  encBouncer.interval(5);
  dirBouncer = Bounce();
  dirBouncer.attach(DIRECTION_SWTCH_PIN);
  dirBouncer.interval(5);
}

void loop() {
  currentTime = millis();
  if(encBouncer.update()){
    if(encBouncer.read() == LOW){
      digitalWrite(TRACK_POWER_PIN, LOW);
      encoderPos = 0;
      #if defined(DEBUG)
        Debug.println("ESTOP");
      #endif
   }
  }
  if(pwrBouncer.update()){
    if(pwrBouncer.read() == LOW){
      trackPWR = !trackPWR;
      digitalWrite(POWER_LED_PIN, trackPWR);
      #if defined(DEBUG)
        Debug.print("POWER");
        Debug.print("\t");
        Debug.println(trackPWR);
      #endif
    }
  }
  if(dirBouncer.update()){
    dir = dirBouncer.read();
    digitalWrite(TRACK_DIR_PIN,dir);
    #if defined(DEBUG)
      Debug.print("DIRECTION");
      Debug.print("\t");
      Debug.println(dir);
    #endif
  }
  if (analogRead(TRACK_AMP_PIN) > TRACK_MAX_AMP) {
    trackPWR = 0;
    digitalWrite(TRACK_POWER_PIN, LOW);
    digitalWrite(POWER_LED_PIN, LOW);
    #if defined(DEBUG)
      Debug.println("SHORT CIRCUIT");
    #endif
  }

  if(trackPWR){
    if(currentTime >= (loopTime + 5)){
      encA = digitalRead(ENCODER_A_PIN);
      encB = digitalRead(ENCODER_B_PIN);
      if((!encA) && (lastA)){
        #if defined(DEBUG)
          Debug.print("ENCODER");
          Debug.print("\t");
        #endif
        if(encB) {
          if (encoderPos < SPEED_STEP) {
            encoderPos ++;
          }
          FwdRev = 1;
        }
        else {
          if(encoderPos > 0){
            encoderPos --;
          }
          FwdRev = 0;
        }
        if(encoderPos>=SPEED_STEP){
          scaled=255;
        }
        else if(encoderPos<=0){
          scaled=0;
        }
        else {
          scaled = START_DUTY_CYCLE + encoderPos * scale_step;
        }
        #if defined(DEBUG)
          Debug.print(encoderPos);
          Debug.print("\t");
          Debug.println(scaled);
        #endif
      }
      lastA = encA;
      loopTime = currentTime;
    }
    analogWrite(TRACK_POWER_PIN, scaled);
  }
}

... и добавил:
А что, не раскрутится?
посмотри выше,при какой скважности начинает крутить Като и Атлас
но, как я там отметил, если подход изменить - то можно на большой частоте сделать.

... и добавил:
Но, КМК DCC работает на 20 кГц.
Ты обвязку выхода на мотор видел?
BEMF и все такое...
КМК, если такое на дуне мутить, проще на цифру перейти :)

Оффлайн qvan22

  • Постоялец
  • ***
  • Сообщений: 174
  • Репутация: +41/-0
  • Откуда: Минск
  • Имя: Владимир
Re: ARDUINO на замену КИРПИЧУ
« Ответ #52 : 13 Марта 2017, 01:53:44 »
сдвиг скважности ШИМ на шаг энкодера рассчитывается как (255-START_DUTY_CYCLE)/SPEED_STEP
Можно попробовать отвязать текущее значение "скорости" от энкодера.
Пусть например раз в 0,1 секунду(через туже millis()) "скорость" растет или падает на какую-то величину, пока не достигнет требуемого значения (вашего encoderPos).
Получим линейное ускорение/торможение, а не рывок за энкодером.



Оффлайн BNSF9399

  • Ветеран
  • *****
  • Сообщений: 1272
  • Репутация: +116/-1
  • Откуда: Москва
  • Имя: Владимир
Re: ARDUINO на замену КИРПИЧУ
« Ответ #53 : 13 Марта 2017, 10:06:17 »
Получим линейное ускорение/торможение, а не рывок за энкодером.
при увеличении значения на 4-5 единиц при спид степе 28, как в крайней версии, он и так линейно ускоряется. даже если ручку крутануть на всю катушку - с места лок не рвет, инерция дает о себе знать.
но, можно и ускорение-торможение сделать, тоже не велика сложность.

Оффлайн gidra

  • Постоялец
  • ***
  • Сообщений: 167
  • Репутация: +23/-0
  • Откуда: Пермь
Re: ARDUINO на замену КИРПИЧУ
« Ответ #54 : 15 Марта 2017, 12:18:10 »
тему читали? какое отношение она к DCC имеет?
Читали...
Непосредственно к дсс, конечно не имеет, только двигатель от этого не меняется..
При правильно настроенном периоде шим ток якоря двигателя незначительно пульсирует, максимально приближаясь к значению тока при питании постоянкой.
При этом, конечно же, обеспечить работу его даже при незначительно меняющейся нагрузке на сверхмалых оборотах без введения обратной связи и соответствующем регулировании не удастся.
Работа с большими периодами шим вроде бы решает проблему сверхмалых оборотов, но тут есть небольшие и не особенно приятные пустячки...
При больших периодах и малой скважности ток якоря за один импульс может успевать дорастать до весьма больших значений, в то время как обороты, вследствие инерционности двигателя, маховика и т.д. вероятнее всего будут гораздо меньше номинала. Во время большой паузы ток якоря наверняка упадёт до нуля, а двигатель будет тормозиться, в том числе возможно, до полной остановки. Средняя скорость при этом будет как раз сверхмалой, только движение будет происходить рывками (практически как шаговый двигатель).
При каждом импульсе, т.к. двигатель будет стартовать с оборотов, близких (или даже равных) нулю, противоЭДС, она же генераторная ЭДС, будет крайне маленькой, или даже нулевой, вследствие чего ток якоря при номинальном напряжении, приложенному к двигателю, будет ограничиваться только сопротивлением обмоток якоря (точнее, iя=( Uном-Еген)/Rя))...
В результате, во время каждого импульса ток якоря может достигать или почти достигать значений пускового тока при номинальном напряжении, а ток этот, как правило в несколько раз превышает ток при номинальной нагрузке.
В итоге, работая в таком режиме ресурс двигателя, особенно коллекторного узла, расходуется семимильными шагами.
А вследствие сильной неравномерности вращения, помимо шума, думаю, и кинематика локомотива разбалтывается гораздо быстрее. А если двигатель "безъякорный", подозреваю, ему может и обмотки деформировать.
В общем, как обычно, у палки два конца, а чудес не бывает...
А при высокой частоте шим, смысла работать " с нуля", действительно,  нет.. Должен быть обеспечен некоторый минимальный (но это не значит, что маленький) ток (а значит и момент, ему пропорциональный) который обеспечит трогание локомотива.

Оффлайн BNSF9399

  • Ветеран
  • *****
  • Сообщений: 1272
  • Репутация: +116/-1
  • Откуда: Москва
  • Имя: Владимир
Re: ARDUINO на замену КИРПИЧУ
« Ответ #55 : 15 Марта 2017, 12:59:59 »
А при высокой частоте шим, смысла работать " с нуля", действительно,  нет.. Должен быть обеспечен некоторый минимальный (но это не значит, что маленький) ток (а значит и момент, ему пропорциональный) который обеспечит трогание локомотива.
так и сделал в последней версии.

Оффлайн Кёф

  • Ветеран
  • *****
  • Сообщений: 2131
  • Репутация: +110/-1
    • Блог Александра a.k.a. Кёф
  • Откуда: Балашиха
  • Имя: Александр/Кёф
Re: ARDUINO на замену КИРПИЧУ
« Ответ #56 : 09 Августа 2017, 23:40:44 »
Видимо логически развиваясь и физически преобразовываясь, это должно выглядеть так и иметь подобный функционал как этот пультик от TOMIX

Блок питания TOMIX ТКС N-DU101-CL http://www.tomytec.co.jp/tomix/necst/5517du101/



Это БП с продвинутым управлением ШИМ.

Вопросы может вызвать только потенциометр для регулировки света.
Потенциометр будет актуален на составах с низковольтными светодиодами со стабилизатором напряжения или DC-DC преобразователем, который позволяет светить светом до того как мотор тронется (по моему опыту до 2,5 вольт).

Вот тут видно (ниже) как в положении EB (ручник) при регулировке света, состав начинает ехать. На первой минуте.




Оффлайн VSergN

  • Ветеран
  • *****
  • Сообщений: 3690
  • Репутация: +179/-6
  • JNR, DRG, Z
  • Откуда: Москва
  • Имя: Сергей
Re: ARDUINO на замену КИРПИЧУ
« Ответ #57 : 10 Августа 2017, 01:58:26 »
Спойлер: (тоже перенёс) (кликните для показа/скрытия)

...который позволяет светить светом до того как мотор тронется (по моему опыту до 2,5 вольт).

Наблюдается интересный пародокс: многие моделисты, "вылизывая" и доводя до максимально возможного совершенства механическую часть своих локомотивов, дабы добиться плавности трогания и ровного хода на малой скорости, стремятся снижать напряжение трогания. С применением такой системы "постоянного освещения" требование к локу становится диаметрально противоположным!  :-[ Т.е. чем выше напряжение трогания, тем надёжнее будет работать система освещения неподвижного состава...
"Палка о двух концах", ёпрст!  :-\

К тому же, все локи должны иметь приблизительно одинаковое напряжение трогания. Иначе придётся постоянно "жонглировать" потенциометром в зависимости от того, какой из локов мы хотим остановить, или же выставлять заведомо заниженную яркость освещения.
« Последнее редактирование: 10 Августа 2017, 02:34:49 от VSergN »

Оффлайн Gematogen

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 6923
  • Репутация: +252/-1
  • Имя: Михаил
Re: ARDUINO на замену КИРПИЧУ
« Ответ #58 : 10 Августа 2017, 03:11:24 »
Спойлер: offtop (кликните для показа/скрытия)
Михаил, DCC

Оффлайн Sid1044

  • Старожил
  • ****
  • Сообщений: 387
  • Репутация: +92/-0
  • Откуда: Москва
  • Имя: Сергей
Re: ARDUINO на замену КИРПИЧУ
« Ответ #59 : 11 Августа 2017, 19:52:55 »
Продвинутый ШИМ у меня зажигает светодиодную ленту (3 диода последовательно) через выпрямитель (еще 2 диода), пока тяга еще стоит.