Помогите новичку
- Войдите на сайт для отправки комментариев
Пнд, 16/04/2012 - 15:28
Собственно вопрос!
Взял на себя непосильную пока! задачу, но отказаться уже поздно, а продолжить не хватает знаний.
Программа выполняет чтение RFID ключей и должна управлять конечным устройством путём переключения PIN12 и PIN13 в логическую единицу на 2 секунды, в коде ниже я смог сделать это с PIN13, но задача сложна для меня тем, что RFID ключей будет 8 шт. и логика работы должна быть такой: считали любой из 8 ключей на PIN12 на 2 сек. лог 1. затем обратно 0, считали ещё раз любой из 8 ключей(необязательно тотже) на PIN13 на 2 сек. лог 1. затем обратно 0. и так в строгой последовательности PIN12->PIN13->PIN12. Коды ключей естественно будут разными.
Помогите пожалуйста!!!
/*
* By Mike Cook April 2009
* Three RFID readers outputing 26 bit Wiegand code to pins:-
* Reader A Pins 4 & 5
* Reader B Pins 6 & 7
* Reader C Pins 8 & 9
* Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
* Then a sting is sent to processing
*/
#include "pins_arduino.h"
/*
* an extension to the interrupt support for arduino.
* add pin change interrupts to the external interrupts, giving a way
* for users to have interrupts drive off of any pin.
* Refer to avr-gcc header files, arduino source and atmega datasheet.
*/
/*
* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
* The PCINT corresponding to the pin must be enabled and masked, and
* an ISR routine provided. Since PCINTs are per port, not per pin, the ISR
* must use some logic to actually implement a per-pin interrupt service.
*/
/* Pin to interrupt map:
* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
*/
volatile uint8_t *port_to_pcmask[] = {
&PCMSK0,
&PCMSK1,
&PCMSK2
};
typedef void (*voidFuncPtr)(void);
volatile static voidFuncPtr PCintFunc[24] = {
NULL };
volatile static uint8_t PCintLast[3];
/*
* attach an interrupt to a specific pin using pin change interrupts.
* First version only supports CHANGE mode.
*/
void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t slot;
volatile uint8_t *pcmask;
if (mode != CHANGE) {
return;
}
// map pin to PCIR register
if (port == NOT_A_PORT) {
return;
}
else {
port -= 2;
pcmask = port_to_pcmask[port];
}
slot = port * 8 + (pin % 8);
PCintFunc[slot] = userFunc;
// set the mask
*pcmask |= bit;
// enable the interrupt
PCICR |= 0x01 << port;
}
void PCdetachInterrupt(uint8_t pin) {
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *pcmask;
// map pin to PCIR register
if (port == NOT_A_PORT) {
return;
}
else {
port -= 2;
pcmask = port_to_pcmask[port];
}
// disable the mask.
*pcmask &= ~bit;
// if that's the last one, disable the interrupt.
if (*pcmask == 0) {
PCICR &= ~(0x01 << port);
}
}
// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
uint8_t bit;
uint8_t curr;
uint8_t mask;
uint8_t pin;
// get the pin states for the indicated port.
curr = *portInputRegister(port+2);
mask = curr ^ PCintLast[port];
PCintLast[port] = curr;
// mask is pins that have changed. screen out non pcint pins.
if ((mask &= *port_to_pcmask[port]) == 0) {
return;
}
// mask is pcint pins that have changed.
for (uint8_t i=0; i < 8; i++) {
bit = 0x01 << i;
if (bit & mask) {
pin = port * 8 + i;
if (PCintFunc[pin] != NULL) {
PCintFunc[pin]();
}
}
}
}
SIGNAL(PCINT0_vect) {
PCint(0);
}
SIGNAL(PCINT1_vect) {
PCint(1);
}
SIGNAL(PCINT2_vect) {
PCint(2);
}
// End of interrupts code and start of the reader code
volatile long reader1 = 0,reader2 = 0, reader3 = 0;
volatile int reader1Count = 0, reader2Count = 0, reader3Count = 0;
void reader1One(void) {
if(digitalRead(4) == LOW){
reader1Count++;
reader1 = reader1 << 1;
reader1 |= 1;
}
}
void reader1Zero(void) {
if(digitalRead(5) == LOW){
reader1Count++;
reader1 = reader1 << 1;
}
}
void reader2One(void) {
if(digitalRead(6) == LOW){
reader2Count++;
reader2 = reader2 << 1;
reader2 |= 1;
}
}
void reader2Zero(void) {
if(digitalRead(7) == LOW){
reader2Count++;
reader2 = reader2 << 1;
}
}
void reader3One(void) {
if(digitalRead(8) == LOW){
reader3Count++;
reader3 = reader3 << 1;
reader3 |= 1;
}
}
void reader3Zero(void) {
if(digitalRead(9) == LOW){
reader3Count++;
reader3 = reader3 << 1;
}
}
void setup()
{
Serial.begin(9600);
// Attach pin change interrupt service routines from the Wiegand RFID readers
PCattachInterrupt(4, reader1One, CHANGE);
PCattachInterrupt(5, reader1Zero, CHANGE);
PCattachInterrupt(6, reader2One, CHANGE);
PCattachInterrupt(7, reader2Zero, CHANGE);
PCattachInterrupt(8, reader3One, CHANGE);
PCattachInterrupt(9, reader3Zero, CHANGE);
delay(10);
// the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
// so this gives a pulse to each reader input line to get the interrupts working properly.
// Then clear out the reader variables.
// The readers are open collector sitting normally at a one so this is OK
for(int i = 4; i<10; i++){
pinMode(i, OUTPUT);
digitalWrite(i, HIGH); // enable internal pull up causing a one
digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
pinMode(i, INPUT);
digitalWrite(i, HIGH); // enable internal pull up
}
delay(10);
// put the reader input variables to zero
reader1 = reader2 = reader3 = 0;
reader1Count = reader2Count = reader3Count = 0;
//digitalWrite(13, HIGH); // show Arduino has finished initilisation
}
void loop() {
if(reader1Count >= 26){
Serial.print(" Reader 1 ");Serial.println(reader1,HEX);
if (reader1 == 0x1BD2421)
digitalWrite(13,HIGH);
delay(2000);
digitalWrite(13,LOW);
if (reader1 != 0x1BD2421)
reader1 = 0;
reader1Count = 0;
delay(2000);
}
}
Код не показывает (или его нет?!)
Алгоритм напишите по строчкам, что бы понятнее было.
Ниже пример кода, в правда работа с тремя RFID ридерами, но это не важно сам поправлю, а вот как решить проблему из перврго поста. /* * By Mike Cook April 2009 * Three RFID readers outputing 26 bit Wiegand code to pins:- * Reader A Pins 4 & 5 * Reader B Pins 6 & 7 * Reader C Pins 8 & 9 * Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved * Then a sting is sent to processing */ #include "pins_arduino.h" /* * an extension to the interrupt support for arduino. * add pin change interrupts to the external interrupts, giving a way * for users to have interrupts drive off of any pin. * Refer to avr-gcc header files, arduino source and atmega datasheet. */ /* * Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts. * The PCINT corresponding to the pin must be enabled and masked, and * an ISR routine provided. Since PCINTs are per port, not per pin, the ISR * must use some logic to actually implement a per-pin interrupt service. */ /* Pin to interrupt map: * D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2 * D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0 * A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1 */ volatile uint8_t *port_to_pcmask[] = { &PCMSK0, &PCMSK1, &PCMSK2 }; typedef void (*voidFuncPtr)(void); volatile static voidFuncPtr PCintFunc[24] = { NULL }; volatile static uint8_t PCintLast[3]; /* * attach an interrupt to a specific pin using pin change interrupts. * First version only supports CHANGE mode. */ void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); uint8_t slot; volatile uint8_t *pcmask; if (mode != CHANGE) { return; } // map pin to PCIR register if (port == NOT_A_PORT) { return; } else { port -= 2; pcmask = port_to_pcmask[port]; } slot = port * 8 + (pin % 8); PCintFunc[slot] = userFunc; // set the mask *pcmask |= bit; // enable the interrupt PCICR |= 0x01 << port; } void PCdetachInterrupt(uint8_t pin) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *pcmask; // map pin to PCIR register if (port == NOT_A_PORT) { return; } else { port -= 2; pcmask = port_to_pcmask[port]; } // disable the mask. *pcmask &= ~bit; // if that's the last one, disable the interrupt. if (*pcmask == 0) { PCICR &= ~(0x01 << port); } } // common code for isr handler. "port" is the PCINT number. // there isn't really a good way to back-map ports and masks to pins. static void PCint(uint8_t port) { uint8_t bit; uint8_t curr; uint8_t mask; uint8_t pin; // get the pin states for the indicated port. curr = *portInputRegister(port+2); mask = curr ^ PCintLast[port]; PCintLast[port] = curr; // mask is pins that have changed. screen out non pcint pins. if ((mask &= *port_to_pcmask[port]) == 0) { return; } // mask is pcint pins that have changed. for (uint8_t i=0; i < 8; i++) { bit = 0x01 << i; if (bit & mask) { pin = port * 8 + i; if (PCintFunc[pin] != NULL) { PCintFunc[pin](); } } } } SIGNAL(PCINT0_vect) { PCint(0); } SIGNAL(PCINT1_vect) { PCint(1); } SIGNAL(PCINT2_vect) { PCint(2); } // End of interrupts code and start of the reader code volatile long reader1 = 0,reader2 = 0, reader3 = 0; volatile int reader1Count = 0, reader2Count = 0, reader3Count = 0; void reader1One(void) { if(digitalRead(4) == LOW){ reader1Count++; reader1 = reader1 << 1; reader1 |= 1; } } void reader1Zero(void) { if(digitalRead(5) == LOW){ reader1Count++; reader1 = reader1 << 1; } } void reader2One(void) { if(digitalRead(6) == LOW){ reader2Count++; reader2 = reader2 << 1; reader2 |= 1; } } void reader2Zero(void) { if(digitalRead(7) == LOW){ reader2Count++; reader2 = reader2 << 1; } } void reader3One(void) { if(digitalRead(8) == LOW){ reader3Count++; reader3 = reader3 << 1; reader3 |= 1; } } void reader3Zero(void) { if(digitalRead(9) == LOW){ reader3Count++; reader3 = reader3 << 1; } } void setup() { Serial.begin(9600); // Attach pin change interrupt service routines from the Wiegand RFID readers PCattachInterrupt(4, reader1One, CHANGE); PCattachInterrupt(5, reader1Zero, CHANGE); PCattachInterrupt(6, reader2One, CHANGE); PCattachInterrupt(7, reader2Zero, CHANGE); PCattachInterrupt(8, reader3One, CHANGE); PCattachInterrupt(9, reader3Zero, CHANGE); delay(10); // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high, // so this gives a pulse to each reader input line to get the interrupts working properly. // Then clear out the reader variables. // The readers are open collector sitting normally at a one so this is OK for(int i = 4; i<10; i++){ pinMode(i, OUTPUT); digitalWrite(i, HIGH); // enable internal pull up causing a one digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt pinMode(i, INPUT); digitalWrite(i, HIGH); // enable internal pull up } delay(10); // put the reader input variables to zero reader1 = reader2 = reader3 = 0; reader1Count = reader2Count = reader3Count = 0; //digitalWrite(13, HIGH); // show Arduino has finished initilisation } void loop() { if(reader1Count >= 26){ Serial.print(" Reader 1 ");Serial.println(reader1,HEX); if (reader1 == 0x1BD2421) digitalWrite(13,HIGH); delay(2000); digitalWrite(13,LOW); if (reader1 != 0x1BD2421) reader1 = 0; reader1Count = 0; delay(2000); } }Почемуто не могу отредактировать 1 пост а второй могу.
Логика по строкам
1.считали любой из 8 ключей на PIN12 на 2 сек. лог 1. затем обратно 0,
2.считали ещё раз любой из 8 ключей(необязательно тотже) на PIN13 на 2 сек. лог 1. затем обратно 0.
3. если считанный ключ не равен ни одному ключу в сравнении то возврат в начало цикла ожидания чтения ключа.
Тут где-то писали, что первый пост специально сделан нередактируемым, ибо студенты задавали вопрос, получали ответ, а потом стирали вопрос, чтобы преподы не отловили. Ну наверно админам форума показалось неитересно иметь ветки с ответами, но без вопросов - малоинформативно.
Кстати, отредактируйте свой второй пост, а то код трудночитаемый. как - http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii
Тут где-то писали, что первый пост специально сделан нередактируемым, ибо студенты задавали вопрос, получали ответ, а потом стирали вопрос, чтобы преподы не отловили. Ну наверно админам форума показалось неитересно иметь ветки с ответами, но без вопросов - малоинформативно.
Кстати, отредактируйте свой второй пост, а то код трудночитаемый. как - http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii
А что, теперь студентов заставляют ардуино программировать или это прикол такой ?
Ну вот где-то заставляют похоже или может какая курсовая работа, я подробностей, к сожалению, не знаю.
Видимо помощи ждать долго!
Чего удалось решить самостоятельно.
Могу прчитать и сравнить 6 ключей.
Управлять аналоговыми выходами с помощью любого ключа.
Осталось следующее:
1.считали любой из 8 ключей на PIN14 на 2 сек. лог 1. затем обратно 0,
2.считали ещё раз любой из 8 ключей(необязательно тотже) на PIN15 на 2 сек. лог 1. затем обратно 0.
Ниже последняя версия кода.
// Reader A Pins 4 & 5 #include "pins_arduino.h" /* Pin to interrupt map: * D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2 * D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0 * A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1 */ volatile uint8_t *port_to_pcmask[] = { &PCMSK0, &PCMSK1, &PCMSK2 }; typedef void (*voidFuncPtr)(void); volatile static voidFuncPtr PCintFunc[24] = { NULL }; volatile static uint8_t PCintLast[3]; void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); uint8_t slot; volatile uint8_t *pcmask; if (mode != CHANGE) { return; } if (port == NOT_A_PORT) { return; } else { port -= 2; pcmask = port_to_pcmask[port]; } slot = port * 8 + (pin % 8); PCintFunc[slot] = userFunc; *pcmask |= bit; PCICR |= 0x01 << port; } void PCdetachInterrupt(uint8_t pin) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *pcmask; if (port == NOT_A_PORT) { return; } else { port -= 2; pcmask = port_to_pcmask[port]; } *pcmask &= ~bit; if (*pcmask == 0) { PCICR &= ~(0x01 << port); } } static void PCint(uint8_t port) { uint8_t bit; uint8_t curr; uint8_t mask; uint8_t pin; curr = *portInputRegister(port+2); mask = curr ^ PCintLast[port]; PCintLast[port] = curr; if ((mask &= *port_to_pcmask[port]) == 0) { return; } for (uint8_t i=0; i < 8; i++) { bit = 0x01 << i; if (bit & mask) { pin = port * 8 + i; if (PCintFunc[pin] != NULL) { PCintFunc[pin](); } } } } SIGNAL(PCINT2_vect) { PCint(2); } volatile long reader1 = 0; volatile int reader1Count = 0; void reader1One(void) { if(digitalRead(4) == LOW){ reader1Count++; reader1 = reader1 << 1; reader1 |= 1; } } void reader1Zero(void) { if(digitalRead(5) == LOW){ reader1Count++; reader1 = reader1 << 1; } } /*void reader2One(void) { if(digitalRead(6) == LOW){ reader2Count++; reader2 = reader2 << 1; reader2 |= 1; } } void reader2Zero(void) { if(digitalRead(7) == LOW){ reader2Count++; reader2 = reader2 << 1; } } void reader3One(void) { if(digitalRead(8) == LOW){ reader3Count++; reader3 = reader3 << 1; reader3 |= 1; } } void reader3Zero(void) { if(digitalRead(9) == LOW){ reader3Count++; reader3 = reader3 << 1; } } */ void setup() { Serial.begin(9600); PCattachInterrupt(4, reader1One, CHANGE); PCattachInterrupt(5, reader1Zero, CHANGE); delay(10); for(int i = 4; i<10; i++){ pinMode(i, OUTPUT); digitalWrite(i, HIGH); digitalWrite(i, LOW); pinMode(i, INPUT); digitalWrite(i, HIGH); } delay(10); reader1 = 0; reader1Count = 0; } void loop() { if(reader1Count >= 26){ Serial.print(" Reader 1 ");Serial.println(reader1,HEX); // Обработка ключа if (reader1 == 0x1BD2421) { pinMode(14, OUTPUT); digitalWrite(14,HIGH); delay (2000); digitalWrite(14,LOW); } else if (reader1 == 0x16F3D32) { pinMode(14, OUTPUT); digitalWrite(14,HIGH); delay (2000); digitalWrite(14,LOW); } else if (reader1 == 0x0000000) { digitalWrite(13,HIGH); delay (2000); digitalWrite(13,LOW); } else if (reader1 == 0x0000000) { digitalWrite(13,HIGH); delay (2000); digitalWrite(13,LOW); } else if (reader1 == 0x0000000) { digitalWrite(13,HIGH); delay (2000); digitalWrite(13,LOW); } else if (reader1 == 0x0000000) { digitalWrite(13,HIGH); delay (2000); digitalWrite(13,LOW); } else { Serial.print(" key not registered in base "); Serial.println(); } reader1 = 0; reader1Count = 0; } }