Быстродействие arduino. Чтение ключа от домофона метаком.
- Войдите на сайт для отправки комментариев
Втр, 27/01/2015 - 05:03
Пытаюсь сделать эмулятор ключа от домофона метаком. Столкнулся с проблемой быстродействием ардуино.
Тайм слот передачи бита от 80 до 200 мкс. В течении тайм слота необходимо 2 раза измерить продолжительность (высокого и низкого уровня тока) сигнала. А у ардуино AnalogRead() — скорость выполнения 110 мкс. В инете нашел способ ускорения ардуино. вот этот ускоритель
#define FASTADC 1 // defines for setting and clearing register bits #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif #if FASTADC // set prescale to 16 sbi(ADCSRA,ADPS2) ; cbi(ADCSRA,ADPS1) ; cbi(ADCSRA,ADPS0) ; #endif
После применения этого "ускорителя" все норм читается, но перестали выполняться свои функции. ( Для удобства хотел разбить код на несколько кусков и вывести из setup loop на отд. функции и вызывать их из основного цикла). Хотел задать вопрос опытным программистам, что делает этот "ускоритель"? и как вызовать свои функции?
Этот код всего лишь устанавливает в трех младших разрядах регистра ADCSRA (одного из регистров управляющих АЦП) комбинацию бит которая переводит АЦП на тактирование частотой 1МГц. При этом AnalogRead() выполняется примерно за 16-18 мкс. Но сделано это чрезмерно замудренно. Проще так:
Повышение частоты ухудшает точность АЦП но не должно никак влиять на выполнение программы. Ищите в ней ошибки.
Alex_Sk Спасибо!
Все работает и код укоротился Вот код может кому пригодится или кто подскажет пути дальнейшей оптимизации. В коде много лишнего из за необходимости отладки ,так как готовых скетчей и библиотек не нашел.
const byte z = 73; // размер массива int t2[73]; // длительность низкий уровень тока или напряжение на Rcч > 400 int t3[73]; // длительность высокий уровень тока или напряжение на Rcч < 400 void setup() { Serial.begin(9600); } void loop() { memset(t2,0,z); // обнуляем массив memset(t3,0,z); unsigned long t=0; while(analogRead(0)>1000) ; // ждем пока нет ключа // записываем все что передает ключ .. потом разберем for(int i=0; i<z; i++) { ADCSRA &= B11111000; // очистить три младших бита ADCSRA |= B00000100; // установить в них комбинацию 100 что дает делитель 16 и тактовую частоту АЦП 1МГц t= micros(); while(analogRead(0)>400); t2[i]= micros() - t; // длительность начало тайм слота низкий уровень тока t= micros(); while(analogRead(0)<400); t3[i]= micros() - t; // длительность окончание тайм слота высокий уровень тока } // для отладки наглядность бля //for(int i=0; i<z; i++) //{ // //Serial.print("t2["); //Serial.print(i); //Serial.print("]= "); //Serial.print(t2[i]); // //Serial.print(" "); //Serial.print("t3= "); //Serial.print(t3[i]); //Serial.print(" "); //Serial.print("t2+t3= "); //Serial.print(t3[i]+t2[i]); //if( t2[i]> (t3[i]+t2[i])/2 ) //{ //Serial.println(" 1"); //} //else //Serial.println(" 0"); // //} //Serial.println("konetc"); byte Sinhro =0; // номер синхро бит в массиве byte TipKey=0; // тип ключа метаком 010 должон быть однако byte Key[35]; byte KeyHex[4]; for(int i=0; i<z; i++) { if (t3[i]>100 ) { Sinhro=i+1; break; // нашли синхро бит? выходим из цикла } } byte q = Sinhro+36 ; byte m=0; for (Sinhro ; Sinhro < q ; Sinhro++) { if ( t2[Sinhro] > (t3[Sinhro]+t2[Sinhro])/2 ) Key[m]=1; else Key[m]=0; m++; } TipKey= Key[2]<<2 | Key[1]<<1 | Key[0]; // проверка правильность чтения for (int i=0; i<4; i++) { int Valid = ( Key[3 +(i*8)] + Key[4 +(i*8)] + Key[5 +(i*8)] + Key[6 +(i*8)] + Key[7 +(i*8)] + Key[8 +(i*8)] + Key[9 +(i*8)] ) % 2; if ( Valid == Key[10 +(i*8)] ) { Serial.print("byte N= "); Serial.print(i+1); Serial.println("valid "); } else { Serial.print("byte N= "); Serial.print(i+1); Serial.println("ERROR "); } } // собираем из массива байты for(int k=0; k < 4 ; k++) { KeyHex[k]= Key[9+(k*8)]<<6 | Key[8+(k*8)]<<5 | Key[7+(k*8)]<<4 | Key[6+(k*8)]<<3 | Key[5+(k*8)]<<2 | Key[4+(k*8)]<<1 | Key[3+(k*8)]; } Serial.println(' '); Serial.print("tipKey="); Serial.println(TipKey); Serial.print("Key="); for(int k=0; k<4 ; k++) { Serial.print(KeyHex[k],HEX); Serial.print(' '); } Serial.println(' '); delay(300); }Код устанавливающий делитель частоты для АЦП не нужен в loop() и тем более в цикле в этой программке. Его достаточно один раз выполнить в Setup(). Это уменьшит время цикла и повысит точность определения длительности посылок.
Логику работы не смотрел, но сразу бросается в глаза куча умножений типа i*8 и k*8 в теле циклов при этом сами переменные циклов i и k используются в несколько раз реже. Если умножение на 8 перенести в условия задания циклов а там где надо i и k применить деление то быстродействие повысится. И в случае операнда 8 лучше использовать бинарный сдвиг который выполняется на порядок-два быстрее: i*8 = i<<3 и i/8 = i>>3
Пока на руках клон ключа, завтра будет орг. ключа с которого сделали этот ключ. Сравню результаты и выложу код оптимизированный учитывая рекомендации Alex_Sk. Не так уж и прост это ардуино для начинающего, чем казалось на первый взляд. Еще раз выражаю благодарность Alex_Sk.
Разница длительности тайм слота оригинала и клона небольшая. Оба ключи читаются норм.
const byte z = 73; // размер массива int t2[73]; // длительность низкий уровень тока или напряжение на Rcч > 400 int t3[73]; // длительность высокий уровень тока или напряжение на Rcч < 400 void setup() { Serial.begin(9600); ADCSRA &= B11111000; // очистить три младших бита ADCSRA |= B00000100; // установить в них комбинацию 100 что дает делитель 16 и тактовую частоту АЦП 1МГц } void loop() { while(analogRead(0)>1000) ; // ждем пока нет ключа delay(30); // читаем memset(t2,0,z); memset(t3,0,z); // обнуляем массив unsigned long t=0; for(int i=0; i<z; i++) { t= micros(); while(analogRead(0)>400); t2[i]= micros() - t; // длительность начало тайм слота низкий уровень тока t= micros(); while(analogRead(0)<400); t3[i]= micros() - t; // длительность окончание тайм слота высокий уровень тока } byte Sinhro = 0; // ищем синхробит for(int i=0; i<z; i++) { if (t3[i]>100 ) { if (i<37) { Sinhro =i+1; break; // нашли синхро бит? выходим из цикла } } } byte Key[35]; byte q = Sinhro+36 ; byte m=0; for (Sinhro ; Sinhro < q ; Sinhro++) { if ( t2[Sinhro] > (t3[Sinhro]+t2[Sinhro]) >> 1) Key[m]=1; else Key[m]=0; m++; } bool er=1; for (int i=0; i<4; i++) { byte Valid = ( Key[3 +(i<<3)] + Key[4 + (i<<3)] + Key[5 + (i<<3)] + Key[6 + (i<<3)] + Key[7 + (i<<3)] + Key[8 + (i<<3)] + Key[9 + (i<<3)] ) % 2; if ( Valid != Key[10 + (i<<3)] ) { Serial.println("ERROR Read "); er=0; break; } } if (er) { if ( Key[2]<<2 | Key[1]<<1 | Key[0] == 2 ) Serial.println("-METACOM- K1233KT2"); Serial.print("KEY HEX = "); for(int i=0; i < 4 ; i++) { byte n= i<<3; //byte as = ( Key[9+n]<<6 | Key[8+n]<<5 | Key[7+n]<<4 | Key[6+n]<<3 | Key[5+n]<<2 | Key[4+n]<<1 | Key[3+n] ); Serial.print( Key[9+n]<<6 | Key[8+n]<<5 | Key[7+n]<<4 | Key[6+n]<<3 | Key[5+n]<<2 | Key[4+n]<<1 | Key[3+n] , HEX); Serial.print(" "); } } Serial.println(" "); Serial.println(" "); delay(500); }Здравствуйте! Подскажите пожалуйста , на каой Arduino был изготовлен эулятор, к каким выводам подключен считыватель ключей? На схеме для считывания кода ключа нет номинолов элементов.
на три года опоздал с вопросом....
Выводы. к которым подключен эмулятор - очевидны из скетча, смотрите внимательнее.
Недавно начал осваивать Arduino,в программировании слаб. В какой строке смотреть?
Я Вам настоятельно рекомендую прочитать все строки.
Просматривал не однократно. По моим догадкам в этой строке-while(analogRead(0)
Какую ардуину можно использовать для данного скетча?
Не корректно читает код ключа. Чтение производилось разными считывателями, ускоритель бесполезный, без него результат тот-же. Всем спасибо за помощь!