Модуль обратной связи DCC (токовый) для LocoNet
-
- Сообщения: 286
- Зарегистрирован: Сб июн 06, 2015 3:26 pm
- Благодарил (а): 26 раз
- Поблагодарили: 10 раз
Re: Модуль обратной связи DCC (токовый) для LocoNet
И форумчане определенно помогли, за что всем ответившим большое СПАСИБО!KitaPro писал(а):Да почему троллил, просто хотел разобраться как это работает
Тут другая мысль пришла - думаю, что в скетче можно отказаться от кольцевого буфера, т.к. программная задержка выключения уже является защитой от "дребезга". Тем самым можно уменьшить занимаемую программой память и немного сократить время цикла контроллера.
Правда пока некуда будет перекинуть освободившуюся мощность, т.к., например, функционал по переключению (силами детектора) стрелок/светофоров в зависимости от занятости участка пока не реализован. Да и вообще - есть ли потребность в таком функционале? Кто-нибудь пользует такие возможности детектора занятости?
- Василий
- Модератор
- Сообщения: 9441
- Зарегистрирован: Чт мар 06, 2008 9:03 am
- Имя: Василий Васильчиков
- Откуда: Северо-западное Болото
- Благодарил (а): 344 раза
- Поблагодарили: 458 раз
- Контактная информация:
Re: Модуль обратной связи DCC (токовый) для LocoNet
Поглядел в скетч, вопрос появился. А зачем датчики в цикле опрашивать? Повесьте на прерывания. Сэкономите массу времени на опросах.
In der Grosse Familie nicht der клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!
-
- Сообщения: 286
- Зарегистрирован: Сб июн 06, 2015 3:26 pm
- Благодарил (а): 26 раз
- Поблагодарили: 10 раз
Re: Модуль обратной связи DCC (токовый) для LocoNet
Хм. Вроде опрос датчиков не в цикле. За один "контроллерный такт" опрашивается только один датчик.Василий писал(а):Поглядел в скетч, вопрос появился. А зачем датчики в цикле опрашивать? Повесьте на прерывания. Сэкономите массу времени на опросах.
Есть опасения, что использование прерываний может повлиять на работу 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
...
- Василий
- Модератор
- Сообщения: 9441
- Зарегистрирован: Чт мар 06, 2008 9:03 am
- Имя: Василий Васильчиков
- Откуда: Северо-западное Болото
- Благодарил (а): 344 раза
- Поблагодарили: 458 раз
- Контактная информация:
Re: Модуль обратной связи DCC (токовый) для LocoNet
Как это не в цикле? GetSensor вызывается же изнутри loop(). Значит в цикле
А каким образом прерывания могут повлиять на работу LocoNet? Если прикинуть: с какой частотой срабатывают датчики? Раз в сто лет относительно частоты выполнения основного цикла. Но при этом в каждой итерации основного цикла вызывается digitalRead();
Если сделать с прерываниями, то при возникновении этого самого прерывания вам нужно будет выполнить digitalRead() максимум 8 раз. То есть вы сэкономите кучу времени в основном цикле. Сама реализация LocoNet прерывания не использует (я так понимаю отсюда же библиотека? https://github.com/timgifford/arduino-on-rails). Мне кажется будет только эффективнее работать.
А каким образом прерывания могут повлиять на работу LocoNet? Если прикинуть: с какой частотой срабатывают датчики? Раз в сто лет относительно частоты выполнения основного цикла. Но при этом в каждой итерации основного цикла вызывается digitalRead();
Если сделать с прерываниями, то при возникновении этого самого прерывания вам нужно будет выполнить digitalRead() максимум 8 раз. То есть вы сэкономите кучу времени в основном цикле. Сама реализация LocoNet прерывания не использует (я так понимаю отсюда же библиотека? https://github.com/timgifford/arduino-on-rails). Мне кажется будет только эффективнее работать.
In der Grosse Familie nicht der клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!
- Василий
- Модератор
- Сообщения: 9441
- Зарегистрирован: Чт мар 06, 2008 9:03 am
- Имя: Василий Васильчиков
- Откуда: Северо-западное Болото
- Благодарил (а): 344 раза
- Поблагодарили: 458 раз
- Контактная информация:
Re: Модуль обратной связи DCC (токовый) для LocoNet
Вас жестоко обманули Вернее просто не договорили. Доберусь до дома, покажу как реализовано у меня. Даже на ProMini можно навесить прерывания почти на все пины.shalex писал(а):p.s. еще один момент - не на все выводы ардуины можно навесить прерывание
Если правильно понял, то выбор не богат:
In der Grosse Familie nicht der клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!
-
- Сообщения: 286
- Зарегистрирован: Сб июн 06, 2015 3:26 pm
- Благодарил (а): 26 раз
- Поблагодарили: 10 раз
Re: Модуль обратной связи DCC (токовый) для LocoNet
Во-первых, увы, нельзя навесить прерывания на все выводы арудины нано.Василий писал(а):Как это не в цикле? GetSensor вызывается же изнутри loop(). Значит в цикле
А каким образом прерывания могут повлиять на работу LocoNet? Если прикинуть: с какой частотой срабатывают датчики? Раз в сто лет относительно частоты выполнения основного цикла. Но при этом в каждой итерации основного цикла вызывается digitalRead();
Если сделать с прерываниями, то при возникновении этого самого прерывания вам нужно будет выполнить digitalRead() максимум 8 раз. То есть вы сэкономите кучу времени в основном цикле. Сама реализация LocoNet прерывания не использует (я так понимаю отсюда же библиотека? https://github.com/timgifford/arduino-on-rails). Мне кажется будет только эффективнее работать.
Во вторых, неважно с какой частотой возникает прерывание -важно, что это прерывает выполнение основной программы, которая в этот момент может заниматься обменом по Loconet и важно сколько по времени будет отрабатывать прерывание. Тут придется городить огород, типа отложенной отправки сообщений (не отправлять же сообщение по каждому прерыванию от датчика, т.к. это занимает время)
В третьих - зачем усложнять, если и так работает )))
-
- Сообщения: 286
- Зарегистрирован: Сб июн 06, 2015 3:26 pm
- Благодарил (а): 26 раз
- Поблагодарили: 10 раз
Re: Модуль обратной связи DCC (токовый) для LocoNet
А вот это интересно! Будет любопытно посмотреть ))Василий писал(а):Вас жестоко обманули Вернее просто не договорили. Доберусь до дома, покажу как реализовано у меня. Даже на ProMini можно навесить прерывания почти на все пины.shalex писал(а):p.s. еще один момент - не на все выводы ардуины можно навесить прерывание
Если правильно понял, то выбор не богат:
p.s. библиотеку брал у Гатова. там примеров побольше http://sourceforge.net/projects/pgahtow ... p/download
- Engineer_Keen
- Сообщения: 313
- Зарегистрирован: Ср фев 24, 2010 11:15 am
- Имя: Василий
- Откуда: Москва
- Поблагодарили: 5 раз
Re: Модуль обратной связи DCC (токовый) для LocoNet
Самый простой способ повесить много линий на прерывание, это собрать их через диоды (ага, хотите еще диодиков попаять? ) по схеме "или" и завести на INT0-INT1, при этом в прерывании проверять какая линия изменилась, но этот фокус не прокатит при одновременном срабатывании нескольких датчиков. Есть варианты контроллеров, у которых куча выводов с названиями PCINTxx (ATmegaXX8, ATmegaXX4, tinyX4), тут реально без дополнительной схемотехники можно сделать каждому прерывание (по одному вектору на каждый порт).
Не знаю точно как работает интерфейс LocoNet, но вот как раз такие вещи я бы на прерывания и вешал! А вот обработка датчиков, это не трудоемкая и не срочная задача ИМХО.
Не знаю точно как работает интерфейс LocoNet, но вот как раз такие вещи я бы на прерывания и вешал! А вот обработка датчиков, это не трудоемкая и не срочная задача ИМХО.
-
- Сообщения: 286
- Зарегистрирован: Сб июн 06, 2015 3:26 pm
- Благодарил (а): 26 раз
- Поблагодарили: 10 раз
Re: Модуль обратной связи DCC (токовый) для LocoNet
Супер! Столько интересных идей за один пост, спасибо!Engineer_Keen писал(а):Самый простой способ повесить много линий на прерывание, это собрать их через диоды (ага, хотите еще диодиков попаять? ) по схеме "или" и завести на 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;
}
- Василий
- Модератор
- Сообщения: 9441
- Зарегистрирован: Чт мар 06, 2008 9:03 am
- Имя: Василий Васильчиков
- Откуда: Северо-западное Болото
- Благодарил (а): 344 раза
- Поблагодарили: 458 раз
- Контактная информация:
Re: Модуль обратной связи DCC (токовый) для LocoNet
Да, я тоже посмотрел внимательно на код, прерывания используются...
Вот недоделка клиента под беспроводные модули. В принципе должно быть понятно. Правда немного AVR магии присутствует
Вот недоделка клиента под беспроводные модули. В принципе должно быть понятно. Правда немного 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 клювом клац-клац!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!
--------------------------------------------------------------------------
Не натягивайте сову на глобус!