Урок 39
Часть 4
Акселерометр LSM6DS3
Продолжаем работать с подключением акселерометра.
В прошлой части занятия мы закончили писать исходный код инициализации датчика.
Сегодня мы уже будем заниматься считыванием показаний нашего датчика по трем осям, которые время от времени нам нужно будет отправлять в шину USART. Для этого создадим функцию
void Accel_ReadAcc(void)
{
_delay_ms(200);
}
//———————————————
void Accel_Ini(void)
Данная функция и будет заниматься обработкой показаний датчика и отправкой их для мониторинга в шину USART. Пока в ней только задержка. Напишем на неё протоип в заголовочный файл
void Accel_Ini(void);
void Accel_ReadAcc(void);
Затем вызовем её в бесконечном цикле в main()
while (1)
{
Accel_ReadAcc();
}
В файле lsm6ds3.c напишем ещё одну функцию
void Accel_GetXYZ(int16_t* pData)
{
}
//———————————————
void Accel_ReadAcc(void)
Данная функция будет заниматься непосредственно выборкой данных из регистров и преобразованием их из пар в единые 16-битные целые числа. Причем данные значения могут быть и отрицательными. Кстати, здесь мы использовали тип значений необычный int16_t. Это то же самое что short. Кто программировал в Keil, тот данный тип знает. Мы постоянно там используем подобного рода типы.
Считывание данных осей постоянно с частотой, которую мы настроили в инициализации, происходит в шесть регистров (для каждой оси — по два)
Так как регистры идут один за другим по адресам, то мы смело можем использовать чтение их всех в одном вызове, так как функция чтения из шины I2C, написанная нами ранее, это вполне предусматривает. Считаем эти данные в предварительно объявленный буфер, а затем с помощью давно известных битовых сдвигов переложим в другой буфер уже в три нормальные 16-битные значения
void Accel_GetXYZ(int16_t* pData)
{
uint8_t buffer[6];
uint8_t i=0;
I2Cx_ReadData(0xD4,LSM6DS3_ACC_GYRO_OUTX_L_XL,6,buffer);
for(i=0;i<3;i++)
{
pData[i] = ((int16_t)((uint16_t)buffer[2*i+1]<<8)+buffer[2*i]);
}
}
Теперь продолжим писать функцию Accel_ReadAcc. Здесь мы также подготовим переменные, вызовем только что написанную функцию и разложим всё уже в свои локальные переменные
void Accel_ReadAcc(void)
{
int16_t buffer[3] = {0};
int16_t xval, yval, zval;
Accel_GetXYZ(buffer);
xval=buffer[0];
yval=buffer[1];
zval=buffer[2];
_delay_ms(200);
Теперь зайдём в файл usart.c и напишем там функцию для отправки данных в шину USART сразу по несколько байтов в самом низу файла, иначе у нас будет очень и очень много кода, если мы будем отправлять данные по одному байту
//—————————————-
void USART_TX (uint8_t *str1, uint8_t cnt)
{
uint8_t i;
for(i=0;i<cnt;i++)
USART_Transmit(str1[i]);
}
//—————————————-
Ну, и, конечно, напишем прототип в файле usart.h
void USART_Transmit( unsigned char data );
void USART_TX (uint8_t *str1, uint8_t cnt);
Вернёмся в нашу недописанную функцию. Сначала добавим глобальную переменную
unsigned char read_buf[10]={0};
char str1[30]={0};
Напишем в функции Accel_ReadAcc отправку данных в текстовом виде в шину USART
zval=buffer[2];
sprintf(str1,«X:%06d Y:%06d Z:%06drn», xval, yval, zval);
USART_TX((uint8_t*)str1,strlen(str1));
_delay_ms(200);
Соберём код, прошьём контроллер и запустим терминальную программу. Правда программа будет несколько другая, так как предыдущая порой не справляется с внушительным потоком. Я решил использовать HyperTerminal. Была найдена версия для современных операционных систем (ссылку дам в конце урока). Настроим в данной программе порт
Нажмём в программе кнопку «call» и Программа нам приблизительно 5 раз в секунду начнёт показывать значения наших осей, правда это не в единицах ускорений свободного падения, но всё это спокойно можно посчитать, учитывая, что у нас максимум 2G, значит 2G будет у нас 32768, а -2G — -32768. Соответственно 1G будет в 2 раза меньше и т.д. Понаклоняем макетницу с платой ненмного в разные стороны, и увидим, что показания постоянно меняются. Показания по оси Z приблизительно 1G означают, что данная ось у нас направлена вертикально и на неё постоянно действует ускорение земного притяжения 1G — она же гравитационная постоянная.
Если вы смотрите мои уроки также и по STM, то вы уже знаете, что я также люблю писать программки под ПК и поэтому мы сейчас немного переделаем код вывода в шину USART, и уже посмотрим данные с осей в виде живого графика (ссылку на программу я также дам ниже). Правда программа работает только на 64-битных ОС. Сначала добавим ещё один глобальный буфер
char str1[30]={0};
uint8_t buf2[14]={0};
Код вывода строки в шину USART пока закомментируем, и напишем код вывода бинарных данных осей. Байты 0x11 и 0x55 вначале отправляем для того, чтобы программа на ПК привязывалась по ним к началу каждой посылки и не путала оси, также убавим немного задержку
//sprintf(str1,»X:%06d Y:%06d Z:%06drn», xval, yval, zval);
//USART_TX((uint8_t*)str1,strlen(str1));
buf2[0]=0x11;
buf2[1]=0x55;
buf2[2]=(uint8_t)(xval>>8);
buf2[3]=(uint8_t)xval;
buf2[4]=(uint8_t)(yval>>8);
buf2[5]=(uint8_t)yval;
buf2[6]=(uint8_t)(zval>>8);
buf2[7]=(uint8_t)zval;
USART_TX(buf2,8);
_delay_ms(30);
Соберём заново код и прошьём контроллер.
Запустим прогамму, настроим также её на наш порт и нажмем Start. Также покрутим немного плату и увидим изменения в графике показаний осей
Мы видим, что показания изредка падают на 0, но это возможно из-за плохих контактов, либо программа просто не успевает обрабатывать, что скорей всего. В текстовом виде у нас никаких сбросов не происходило.
Предыдущая часть Программирование МК AVR Следующий урок
Техническая документация:
Документация на оценочную плату
Программа визуализации показаний
Приобрести плату Atmega 328p Pro Mini можно здесь.
Приобрести программатор USBASP USBISP с адаптером можно здесь USBASP USBISP 3.3 с адаптером
Смотреть ВИДЕОУРОК (нажмите на картинку)
День добрый!
Очень хочется увидеть урок с oled дисплеем 0.96" (шина I2c или TWI). Не планируете такой?
К сожалению, у меня такого нет.
Понял, ну если будет у Вас возможность и желание попробовать его — буду рад освещению процесса тут. Дисплей интересный — пробовал играться с ним через arduino ide с готовой библиотекой. А вот нормально запустить его просто через atmel studio не вышло. Максимум инициализировать и точки ставить получалось.
Ну да, буду иметь в виду. То что работает с готовыми библиотеками ардуино, всегда нелегко запустить в Atmel Studio. Вот как раз сейчас я этим и занимаюсь. Пишу сценарий для работы с LAN-микросхемой enc28j60 под Atmel Studio, для которой под ардуино есть куча библиотек, приходится в них копаться и выкапывать оттуда некоторый передовой опыт.
LAN модуль — это тоже интересно! Спасибо за уроки … очень полезно))
не устанавливается ns accel monitor, где можно скачать рабочую программу?
Всё должно устанавливаться. Какая ошибка?
товарищ,
Большое спасибо за вашу публикацию, мне очень помогло использование atmega328pb с LSM6DS3
Я использовал компилятор codevisionavr, и все работало нормально.
если бы все знания были распространены, немой был бы намного лучше, и у нас было бы меньше бедности и социального неравенства
Извините за ошибку перевода Google, здесь в Бразилии мы говорим на португальском
объятий,
Роналду Мартинс