Я описал как работать с АЦП в этой статье.
Теперь расскажу как работает инфракрасный датчик.
У инфракрасных датчиков имеется (ВНЕЗАПНО!) инфракрасный светодиод ( LED ) с линзой который излучает узкий световой луч. Это излучение распространяется и отражается от объектов находящихся в поле зрения сенсора. Угол отражения напрямую зависит от расстояния до объекта.
Отраженный луч через другую линзу попадает на позиционно-чувствительный фотоэлемент ( PSD ). Это значит что от местоположения падающего на фотоэлемент луча зависит его проводимость.
Проводимость преобразуется в напряжение и с его помощью можно вычислить расстояние до объекта.
У дальномеров может быть как цифровой так и аналоговый выход, если выход аналоговый нужно использовать АЦП микроконтроллера для преобразования аналогового напряжения в двоичный код.
Слева приведён типичный график зависимости напряжения от расстояния датчика Sharp. Как видно он не является линейным. К тому же минимально измеряемое расстояние ограничено особенностями датчика. Выходное напряжение резко падает на определённом расстоянии и 1 значению напряжения соответствует 2 расстояния, об этом необходимо помнить при работе с сенсором.
Однако в даташите приведён также график зависимости обратного значения расстояния ( 1/см ) от напряжения и как видно на начальном участке он почти линейный и его можно использовать для вычисления формулы преобразования напряжения в расстояния.
Для этого нужно измерять выдаваемое микроконтроллером значение АЦП ( или напряжения, но с АЦП легче работать ) на живом датчике. Затем в программе обработки табличных данных ( я использовал mathcad ) построить новый график по полученным точкам.
По оси ординат (вертикальная) выставляются обратные значения расстояния, которое вычисляется по формуле которая указана в даташите датчика.
По оси ординат значения АЦП.
Теперь нужно найти уравнение прямой (синий цвет) которая проходит ближе всего ко всем точкам графика (красный цвет).
Получив уравнение можно сделать обобщение и сказать что зависимость между напряжением и расстоянием следующая
1 / (d + k) = a ⋅ ADC + b
d - расстояние в сантиметрах
k - корректирующая константа (взята из даташита)
ADC - это значение АЦП
a,b - линейные члены (значение выходит из уравнения линии тренда)
Теперь расскажу как работает инфракрасный датчик.
( В самом простом случае ) У него есть 3 вывода: Vcc - питание GND - земля и Vo - с которого снимаем данные.
В зависимости от расстояния меняется напряжение на выводе Vo, всё что остаётся это перевести данные из аналога в цифру.
В зависимости от расстояния меняется напряжение на выводе Vo, всё что остаётся это перевести данные из аналога в цифру.
Отраженный луч через другую линзу попадает на позиционно-чувствительный фотоэлемент ( PSD ). Это значит что от местоположения падающего на фотоэлемент луча зависит его проводимость.
Проводимость преобразуется в напряжение и с его помощью можно вычислить расстояние до объекта.
У дальномеров может быть как цифровой так и аналоговый выход, если выход аналоговый нужно использовать АЦП микроконтроллера для преобразования аналогового напряжения в двоичный код.
Слева приведён типичный график зависимости напряжения от расстояния датчика Sharp. Как видно он не является линейным. К тому же минимально измеряемое расстояние ограничено особенностями датчика. Выходное напряжение резко падает на определённом расстоянии и 1 значению напряжения соответствует 2 расстояния, об этом необходимо помнить при работе с сенсором.
Однако в даташите приведён также график зависимости обратного значения расстояния ( 1/см ) от напряжения и как видно на начальном участке он почти линейный и его можно использовать для вычисления формулы преобразования напряжения в расстояния.
Для этого нужно измерять выдаваемое микроконтроллером значение АЦП ( или напряжения, но с АЦП легче работать ) на живом датчике. Затем в программе обработки табличных данных ( я использовал mathcad ) построить новый график по полученным точкам.
По оси ординат (вертикальная) выставляются обратные значения расстояния, которое вычисляется по формуле которая указана в даташите датчика.
По оси ординат значения АЦП.
Теперь нужно найти уравнение прямой (синий цвет) которая проходит ближе всего ко всем точкам графика (красный цвет).
Получив уравнение можно сделать обобщение и сказать что зависимость между напряжением и расстоянием следующая
1 / (d + k) = a ⋅ ADC + b
d - расстояние в сантиметрах
k - корректирующая константа (взята из даташита)
ADC - это значение АЦП
a,b - линейные члены (значение выходит из уравнения линии тренда)
Перед равно, значение обратной величины расстояния, после уравнение полученной прямой.
Из этого можно вывести расстояние.
d = (1 / (a ⋅ ADC + b)) – k
В принципе по этой формуле можно вычислить расстояние, но тут приходится работать с дробями на микроконтроллере проще оперировать целыми числами, поэтому нужно упростить формулу и перевести в большие множители разделив частное на линейный член.
d = (1 / a) / (ADC + b / a) – k
К примеру у Sharp GP2D12 полученная в итоге формула выглядит так
d = (6787 / (ADC - 3)) - 4
Осталось проверить чтобы значение АЦП было больше 3 иначе будет деление на 0 или отрицательное расстояние.
Если просто нужно узнать есть ли предмет перед датчиком, можно проверять чтобы значение ADC не превышало необходимое нам, тогда не нужно делать никаких расчётов и просто экспериментально подобрать значения, можно даже в Proteus.
Если просто нужно узнать есть ли предмет перед датчиком, можно проверять чтобы значение ADC не превышало необходимое нам, тогда не нужно делать никаких расчётов и просто экспериментально подобрать значения, можно даже в Proteus.
#define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> void check_sensors() { if(ADCSRA & 1<<ADSC) // Если закончилось измерение напряжения { unsigned int ADCdata; ADCdata = ADCW; // В ADCW хранится напряжение в двоичном коде if(ADCdata <= 615) // Грубое измерение 13 см и 2.5 Вольт для SHARP GP2D120 { делать_что_угодно; // TROLOLOLOLO } ADCSRA |= (1<<ADSC); // Регистр для начала нового преобразования 0b01000000 } int main() { ADMUX = 0x00; // Считаем ножку PA0 ADCSRA |= (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1); // выставляем нужные биты while(1) { if(ADCSRA & 1<<ADSC) // ИЛИ можно здесь проверить закончилось ли преобразование чтоб меньше времени тратить { check_sensors(); } // bla bla bla } } // Или можно узнать точное значение с помощью прерывания, когда АЦП подсчитает напряжение ISR(ADC_vect) { ADCdata = ADCW; voltage_0 = ADCdata * 48875 / 10000; // ( 5000 милливольт / 1023 ) = 4.8875 ( милливольт в 1 бите ) voltage = voltage_0 % 10000 / 1000; voltage_2 = voltage_0 % 1000 / 100; voltage_3 = voltage_0 % 100 / 10; voltage_4 = voltage_0 % 10; if (ADCdata > 3) // чтоб не делить на 0 { range = (6787 / (ADCdata - 3)) - 4; } ADCSRA = ADCSRA | 0x40;// начинаем новый пересчёт 0b01000000 }
Комментариев нет :
Отправить комментарий