Модуль обратной связи DCC (токовый) для LocoNet

Вопросы и ответы связанные с цифровым управлением, аналоговой автоматикой и их элементами
Сообщение
Автор
shalex
Сообщения: 286
Зарегистрирован: Сб июн 06, 2015 3:26 pm
Благодарил (а): 26 раз
Поблагодарили: 10 раз

Re: Модуль обратной связи DCC (токовый) для LocoNet

#151 Непрочитанное сообщение shalex »

KitaPro писал(а):Да почему троллил, просто хотел разобраться как это работает
И форумчане определенно помогли, за что всем ответившим большое СПАСИБО!


Тут другая мысль пришла - думаю, что в скетче можно отказаться от кольцевого буфера, т.к. программная задержка выключения уже является защитой от "дребезга". Тем самым можно уменьшить занимаемую программой память и немного сократить время цикла контроллера.

Правда пока некуда будет перекинуть освободившуюся мощность, т.к., например, функционал по переключению (силами детектора) стрелок/светофоров в зависимости от занятости участка пока не реализован. Да и вообще - есть ли потребность в таком функционале? Кто-нибудь пользует такие возможности детектора занятости?

Аватара пользователя
Василий
Модератор
Сообщения: 9407
Зарегистрирован: Чт мар 06, 2008 9:03 am
Имя: Василий Васильчиков
Откуда: Северо-западное Болото
Благодарил (а): 334 раза
Поблагодарили: 435 раз
Контактная информация:

Re: Модуль обратной связи DCC (токовый) для LocoNet

#152 Непрочитанное сообщение Василий »

Поглядел в скетч, вопрос появился. А зачем датчики в цикле опрашивать? Повесьте на прерывания. Сэкономите массу времени на опросах.
In der Grosse Familie nicht der клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!

shalex
Сообщения: 286
Зарегистрирован: Сб июн 06, 2015 3:26 pm
Благодарил (а): 26 раз
Поблагодарили: 10 раз

Re: Модуль обратной связи DCC (токовый) для LocoNet

#153 Непрочитанное сообщение shalex »

Василий писал(а):Поглядел в скетч, вопрос появился. А зачем датчики в цикле опрашивать? Повесьте на прерывания. Сэкономите массу времени на опросах.
Хм. Вроде опрос датчиков не в цикле. За один "контроллерный такт" опрашивается только один датчик.
Есть опасения, что использование прерываний может повлиять на работу Loconet-интерфейса.

p.s. еще один момент - не на все выводы ардуины можно навесить прерывание
Если правильно понял, то выбор не богат:

Код: Выделить всё

...
Board	Digital Pins Usable For Interrupts
Uno, Nano, Mini, other 328-based	2, 3
Mega, Mega2560, MegaADK	2, 3, 18, 19, 20, 21
Micro, Leonardo, other 32u4-based	0, 1, 2, 3, 7
Zero	all digital pins, except 4
Due	all digital pins
...
https://www.arduino.cc/en/Reference/AttachInterrupt

Аватара пользователя
Василий
Модератор
Сообщения: 9407
Зарегистрирован: Чт мар 06, 2008 9:03 am
Имя: Василий Васильчиков
Откуда: Северо-западное Болото
Благодарил (а): 334 раза
Поблагодарили: 435 раз
Контактная информация:

Re: Модуль обратной связи DCC (токовый) для LocoNet

#154 Непрочитанное сообщение Василий »

Как это не в цикле? GetSensor вызывается же изнутри loop(). Значит в цикле :)

А каким образом прерывания могут повлиять на работу LocoNet? Если прикинуть: с какой частотой срабатывают датчики? Раз в сто лет относительно частоты выполнения основного цикла. Но при этом в каждой итерации основного цикла вызывается digitalRead();

Если сделать с прерываниями, то при возникновении этого самого прерывания вам нужно будет выполнить digitalRead() максимум 8 раз. То есть вы сэкономите кучу времени в основном цикле. Сама реализация LocoNet прерывания не использует (я так понимаю отсюда же библиотека? https://github.com/timgifford/arduino-on-rails). Мне кажется будет только эффективнее работать.
In der Grosse Familie nicht der клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!

Аватара пользователя
Василий
Модератор
Сообщения: 9407
Зарегистрирован: Чт мар 06, 2008 9:03 am
Имя: Василий Васильчиков
Откуда: Северо-западное Болото
Благодарил (а): 334 раза
Поблагодарили: 435 раз
Контактная информация:

Re: Модуль обратной связи DCC (токовый) для LocoNet

#155 Непрочитанное сообщение Василий »

shalex писал(а):p.s. еще один момент - не на все выводы ардуины можно навесить прерывание
Если правильно понял, то выбор не богат:
Вас жестоко обманули :) Вернее просто не договорили. Доберусь до дома, покажу как реализовано у меня. Даже на ProMini можно навесить прерывания почти на все пины.
In der Grosse Familie nicht der клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!

shalex
Сообщения: 286
Зарегистрирован: Сб июн 06, 2015 3:26 pm
Благодарил (а): 26 раз
Поблагодарили: 10 раз

Re: Модуль обратной связи DCC (токовый) для LocoNet

#156 Непрочитанное сообщение shalex »

Василий писал(а):Как это не в цикле? GetSensor вызывается же изнутри loop(). Значит в цикле :)

А каким образом прерывания могут повлиять на работу LocoNet? Если прикинуть: с какой частотой срабатывают датчики? Раз в сто лет относительно частоты выполнения основного цикла. Но при этом в каждой итерации основного цикла вызывается digitalRead();

Если сделать с прерываниями, то при возникновении этого самого прерывания вам нужно будет выполнить digitalRead() максимум 8 раз. То есть вы сэкономите кучу времени в основном цикле. Сама реализация LocoNet прерывания не использует (я так понимаю отсюда же библиотека? https://github.com/timgifford/arduino-on-rails). Мне кажется будет только эффективнее работать.
Во-первых, увы, нельзя навесить прерывания на все выводы арудины нано.

Во вторых, неважно с какой частотой возникает прерывание -важно, что это прерывает выполнение основной программы, которая в этот момент может заниматься обменом по Loconet и важно сколько по времени будет отрабатывать прерывание. Тут придется городить огород, типа отложенной отправки сообщений (не отправлять же сообщение по каждому прерыванию от датчика, т.к. это занимает время)

В третьих - зачем усложнять, если и так работает )))

shalex
Сообщения: 286
Зарегистрирован: Сб июн 06, 2015 3:26 pm
Благодарил (а): 26 раз
Поблагодарили: 10 раз

Re: Модуль обратной связи DCC (токовый) для LocoNet

#157 Непрочитанное сообщение shalex »

Василий писал(а):
shalex писал(а):p.s. еще один момент - не на все выводы ардуины можно навесить прерывание
Если правильно понял, то выбор не богат:
Вас жестоко обманули :) Вернее просто не договорили. Доберусь до дома, покажу как реализовано у меня. Даже на ProMini можно навесить прерывания почти на все пины.
А вот это интересно! Будет любопытно посмотреть ))

p.s. библиотеку брал у Гатова. там примеров побольше http://sourceforge.net/projects/pgahtow ... p/download

Аватара пользователя
Engineer_Keen
Сообщения: 313
Зарегистрирован: Ср фев 24, 2010 11:15 am
Имя: Василий
Откуда: Москва
Поблагодарили: 5 раз

Re: Модуль обратной связи DCC (токовый) для LocoNet

#158 Непрочитанное сообщение Engineer_Keen »

Самый простой способ повесить много линий на прерывание, это собрать их через диоды (ага, хотите еще диодиков попаять? :lol: ) по схеме "или" и завести на INT0-INT1, при этом в прерывании проверять какая линия изменилась, но этот фокус не прокатит при одновременном срабатывании нескольких датчиков. Есть варианты контроллеров, у которых куча выводов с названиями PCINTxx (ATmegaXX8, ATmegaXX4, tinyX4), тут реально без дополнительной схемотехники можно сделать каждому прерывание (по одному вектору на каждый порт).
Не знаю точно как работает интерфейс LocoNet, но вот как раз такие вещи я бы на прерывания и вешал! А вот обработка датчиков, это не трудоемкая и не срочная задача ИМХО.

shalex
Сообщения: 286
Зарегистрирован: Сб июн 06, 2015 3:26 pm
Благодарил (а): 26 раз
Поблагодарили: 10 раз

Re: Модуль обратной связи DCC (токовый) для LocoNet

#159 Непрочитанное сообщение shalex »

Engineer_Keen писал(а):Самый простой способ повесить много линий на прерывание, это собрать их через диоды (ага, хотите еще диодиков попаять? :lol: ) по схеме "или" и завести на INT0-INT1, при этом в прерывании проверять какая линия изменилась, но этот фокус не прокатит при одновременном срабатывании нескольких датчиков. Есть варианты контроллеров, у которых куча выводов с названиями PCINTxx (ATmegaXX8, ATmegaXX4, tinyX4), тут реально без дополнительной схемотехники можно сделать каждому прерывание (по одному вектору на каждый порт).
Не знаю точно как работает интерфейс LocoNet, но вот как раз такие вещи я бы на прерывания и вешал! А вот обработка датчиков, это не трудоемкая и не срочная задача ИМХО.
Супер! Столько интересных идей за один пост, спасибо!
Однако не уверен, что буду пытаться их применить в этом устройстве )

Пытаюсь курить код библиотеки Loconet и почему то мне думается, что интерфейс с Loconet сделан на прерываниях.
Встречаю в конcтрукторе вызовы sbi, например. Но все выглядит немного низкоуровневым, большой знаток AVR, видимо делал. например вот такая штука:

Код: Выделить всё

void initLocoNetHardware( LnBuf *RxBuffer )
{
  lnRxBuffer = RxBuffer ;

  // Set the RX line to Input
  cbi( LN_RX_DDR, LN_RX_BIT ) ;

  // Set the TX line to Inactive
  LN_SW_UART_SET_TX_HIGH(LN_TX_PORT, LN_TX_BIT);

#ifdef LN_INIT_COMPARATOR
  LN_INIT_COMPARATOR();	
#else
  // First Enable the Analog Comparitor Power, 
  // Set the mode to Falling Edge
  // Enable Analog Comparator to Trigger the Input Capture unit
  // ACSR = (1<<ACI) | (1<<ACIS1) | (1<<ACIC) ;

  // Turn off the Analog Comparator
  ACSR = 1<<ACD;
  // The noise canceler is enabled by setting the Input Capture Noise Canceler (ICNCn) bit in 
  // Timer/Counter Control Register B (TCCRnB). When enabled the noise canceler introduces addi- 
  // tional four system clock cycles of delay from a change applied to the input, to the update of the 
  // ICRn Register. The noise canceler uses the system clock and is therefore not affected by the 
  // prescaler.
  TCCR1B |= (1<<ICNC1) ;    		// Enable Noise Canceler 
#endif
  lnState = LN_ST_IDLE ;
  //Clear StartBit Interrupt flag
  sbi( LN_SB_INT_STATUS_REG, LN_SB_INT_STATUS_BIT );
  //Enable StartBit Interrupt
  sbi( LN_SB_INT_ENABLE_REG, LN_SB_INT_ENABLE_BIT );
  // Set Timer Clock Source 
  LN_TMR_CONTROL_REG = (LN_TMR_CONTROL_REG & 0xF8) | LN_TMR_PRESCALER;
}

Аватара пользователя
Василий
Модератор
Сообщения: 9407
Зарегистрирован: Чт мар 06, 2008 9:03 am
Имя: Василий Васильчиков
Откуда: Северо-западное Болото
Благодарил (а): 334 раза
Поблагодарили: 435 раз
Контактная информация:

Re: Модуль обратной связи DCC (токовый) для LocoNet

#160 Непрочитанное сообщение Василий »

Да, я тоже посмотрел внимательно на код, прерывания используются...

Вот недоделка клиента под беспроводные модули. В принципе должно быть понятно. Правда немного AVR магии присутствует :)

Код: Выделить всё

/*
 * Wireless "S88" sensor module for Arduino Pro Mini clone
 * Written by Vasily S. Vasilchikov
 * doublehead@mail.ru
 * v 0.1 05 Nov 2015
 * http://scaletrainsclub.com
 *  
 *  
*/

// wireless
#include <SPI.h>
#include <RH_NRF24.h>

RH_NRF24 nrf24;

// sensors

byte stationID=1;
volatile unsigned int sensors=0;
volatile unsigned int sensorsOld=0;
unsigned int sensorsData=0;
const byte externalLed=13; //data output pin=13

void setup() {

  Serial.begin(9600);
  Serial.println("starting");
 
  // init sensors
  
  pinMode(externalLed, OUTPUT); // external led for TxRx signalling
  digitalWrite(externalLed, LOW);   //LED off
  pinMode(A0, INPUT_PULLUP); //sensor 01
  pinMode(A1, INPUT_PULLUP); //sensor 02
  pinMode(A2, INPUT_PULLUP); //sensor 03
  pinMode(A3, INPUT_PULLUP); //sensor 04
  pinMode(A4, INPUT_PULLUP); //sensor 05
  pinMode(A5, INPUT_PULLUP); //sensor 06
  pinMode(0, INPUT_PULLUP);  //sensor 07 - RX pin on 6 pin header
  pinMode(1, INPUT_PULLUP);  //sensor 08
  pinMode(2, INPUT_PULLUP);  //sensor 09
  pinMode(3, INPUT_PULLUP);  //sensor 10
  pinMode(4, INPUT_PULLUP);  //sensor 11
  pinMode(5, INPUT_PULLUP);  //sensor 12
  pinMode(6, INPUT_PULLUP);  //sensor 13
  pinMode(7, INPUT_PULLUP);  //sensor 14
  pinMode(8, INPUT_PULLUP);  //sensor 15

  // some AVR magic here
  
  cli();        // switch interrupts off   
  
  EICRA = 0b00001111;    // set wanted flags (rising level interrupt)
  
  PCICR =0x07;  // Enable PCINT0 PCINT1 PCINT2 interrupt group

  // mask all pins we would like to use (D8, A0-A5, D0-D7) D1&D0 temporary disabled 'cause it's RXTX pins :)
  
  PCMSK0 = 0b00000000;                      // Mini Pro Pins ..  ..  D13 D12 D11 D10 D9  D8  
  PCMSK1 = 0b00000000;                      // Mini Pro pins ..  ..  A5  A4  A3  A2  A1  A0
  PCMSK2 = 0b11111100;                      // Mini Pro pins D7  D6  D5  D4  D3  D2  D1  D0
  
  sei();  

  // now we can hide our magic wand

  // init nrf24
  if (!nrf24.init())
    Serial.println("init failed");
  // Defaults after init are 2.402 GHz (channel 2), 2Mbps, 0dBm
  if (!nrf24.setChannel(stationID))
    Serial.println("setChannel failed");
  if (!nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
    Serial.println("setRF failed");   
 if (!nrf24.init())
    Serial.println("init failed");
  // Defaults after init are 2.402 GHz (channel 2), 2Mbps, 0dBm
  if (!nrf24.setChannel(stationID))
    Serial.println("setChannel failed");
  if (!nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
    Serial.println("setRF failed");   

}

ISR(PCINT0_vect){
  cli();
  if (!digitalRead(8)) {
      bitSet(sensors,14);
  }
  sei();
}

ISR(PCINT1_vect){
  cli();
  if (!digitalRead(A0)) {
      bitSet(sensors,0);
  }
  if (!digitalRead(A1)) {
      bitSet(sensors,1);
  }
  if (!digitalRead(A2)) {
      bitSet(sensors,2);
  }
  if (!digitalRead(A3)) {
      bitSet(sensors,3);
  }
  if (!digitalRead(A4)) {
      bitSet(sensors,4);
  }
  if (!digitalRead(A5)) {
      bitSet(sensors,5);
  }
  
  sei();
}

ISR(PCINT2_vect){
  cli();
  if (!digitalRead(0)) {
      bitSet(sensors,6);
  }
  if (!digitalRead(1)) {
      bitSet(sensors,7);
  }
  if (!digitalRead(2)) {
      bitSet(sensors,8);
  }
  if (!digitalRead(3)) {
      bitSet(sensors,9);
  }
  if (!digitalRead(4)) {
      bitSet(sensors,10);
  }
  if (!digitalRead(5)) {
      bitSet(sensors,11);
  }
  if (!digitalRead(6)) {
      bitSet(sensors,12);
  }
  if (!digitalRead(7)) {
      bitSet(sensors,13);
  }
  sei();
}

void loop() {

  if(sensors!=0){
      // send Data
      sensorsData=sensors;
   Serial.println(sensors,BIN);
  Serial.println("----------------");
     if(sendData(sensorsData)){
          sensorsOld=sensorsData;
       
      }      
      sensors=0;
                  
  }
}

bool sendData(unsigned int InData){
  
  // make array
  uint8_t data[4]; // we need to send 4 bytes: 1 - this module ID, 2 & 3 sensors data, 4 - simple CRC (XOR of 1-3 bytes)
  data[0]=stationID;
  data[1]=InData;
  data[2]=InData>>8;
  data[3]=data[0] ^ data[1] ^ data[2];
  Serial.println("send data");
  nrf24.send(data, 4);  
  if(nrf24.waitPacketSent()){
     return true;  
  };
 
   return false;
}
In der Grosse Familie nicht der клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!

Ответить

Вернуться в «Цифровое управление, Аналоговая автоматика и их элементы»