Цифровой акселерометр MMA7260Q и ATmega8, измерения углов крена и тангажа +бонус

При подборе модуля цифрового компаса натолкнулся на акселерометры, датчики ускорения, точнее на MMA7260Q от Freescale. Акселерометры, как не удивительно, реагируют на ускорения (в том числе и на ускорения всемирного тяготения) и как следствие с второго закона Ньютона, на равнодействующую силу, приложенную к датчику.

То есть, с его помощью можно измерять вибрации, движение, удары, углы крена и тангажа. MMA7260Q является 3-х осевым датчиком с аналоговым выходом, то есть он перекрывает все 3-х мерное пространство. Измерительным элементом внутри датчика, как это не удивительно звучит, является переменные конденсаторы, обкладки которых двигаются под воздействием внешней силы. MMA7260Q имеет регулируемый диапазон чувствительности, выбрать который можно комбинацией логических уровней на пинах g-Select1, g-Select2.

комбинации G-select1,2
Так как датчик поставляется в корпусе QFN-16, то для удобства пришлось сделать ему макетку:
фото макетки с MMA7260Q
Макетка вышла немного перетравленной, потому, что забыл ее с хлорного железа вовремя вынуть, и некоторые дорожки существенно подтравились.
У меня чаще всего используется питающее напряжение 5В, то в схему добавил 3.3В стабилизатор напряжения LP2980-3.3, для питания MMA7260Q. Снимать сигнал, согласно рекомендациям даташита, будем через RC цепочку 1кОм и 0,1мкФ. Также, с обоих сторон по питанию навешаем конденсаторов, с внешней стороны тантал на 68мкФ и керамика на 0,1мкФ, а с внутренней – керамика на 1мкФ. При работе с датчиком не забываем подключать ножку Sleep mode к +3.3В, через подтягивающий резистор, иначе никакого сигнала не получим.
Подключил канал Х к аналоговому входу своего логического анализатора и покрутил-постукал-погрюкал платкой с датчиком по столу. Получилась вот такая картинка:

Можно будет подключить к АЦП ATmega8 и измерять проекции ускорения всемирного тяготения на ортогональные оси X, Y, Z. А также полное ускорение sqrt(ax^2+ay^2+az^2). Чем и займемся в данной заметке. Подключим наш MMA7260Q к ATmega8, как показано на схеме:

Источник тактирования микроконтроллера – внутренний RC генератор на 1МГц. Конденсаторы С1,С2,С3,С9,С6,С4,С11 – керамические на 0,1мкф, С10 – керамический на 1мкФ С8 – танталовый на 68мкФ, а С5 и С7 – электролиты на 100 и 200мкФ соответственно. Резисторы R2,R4,R5,R6,R7 по 1кОм, R1 – 10кОм, потенциометр VR1 – 10кОм, R3 - ограничивающий ток через подсветку ЖКИ, 17 Ом.
Выводы G-Select1, G-Select2 мы подключим к земле, тем самым получим предел измерения +-1.5g и чувствительность 0.8В/g. Прошивка микроконтроллера тривиальна, периодически опрашиваются входа АЦП PC0-PC2 (так как измерять ускорения мы будем не более 1g, то источником опорного напряжения будем использовать внутренний на 2.56В). Интересующие ускорение получается как ax=(ADC-ZERO_X)*2.56/(1024*0.8), где ZERO_X – калибровочная константа, которая рассчитывается как ZERO_X=U/(2.56/1024), где U – напряжение на выходе датчика, когда действующее ускорение по оси Х равно нулю. Аналогично вычисляются ay и az. Также вычисляем длину вектора ускорения, а=sqrt(ax*ax+ay*ay+az*az), для чего используем тип double, работа с которым скушает добрую часть памяти программ ATmega8.
Код программы прокомментирован, так что разобраться в нем не составит труда. Если же возникнут трудности, то почитайте про работу с АЦП и символьным ЖК индикатором (этот макет является комбинацией работы с АЦП и ЖКИ)

  1. #include <avr/io.h> //Библиотека ввода/вывода
  2. #include <math.h.> //Библиотека математических операций
  3.  
  4. #define RS 2 //RS=PD2
  5. #define E 3 //E=PD3
  6.  
  7. #define TIME 10
  8. //Константа временной задержки для ЖКИ
  9. //Тактовая частота 4МГц
  10.  
  11. #define ZERO_X 0x026c //Расчетная константа для координаты x
  12. #define ZERO_Y 0x0258 //Расчетная константа для координаты y
  13. #define ZERO_Z 0x029c //Расчетная константа для координаты z
  14.  
  15. int u=0; //Переменная напряжения на ADC
  16.  
  17. int x,y,z; //Переменная координат ax,ay,az
  18.  
  19. void pause (unsigned int a) //Функция паузы
  20. {
  21. unsigned int i; //декларация переменной для функции паузы
  22. for(i=a;i>0;i--); //цикл задержки
  23. }
  24.  
  25. //Программа передачи команды в ЖКИ
  26. void lcd_com (unsigned char lcd)
  27. {
  28. unsigned char temp; //
  29.  
  30. temp=(lcd&~(1<<RS))|(1<<E); //RS=0 –указывает на подачу команда для ЖКИ
  31. PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E
  32. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  33. PORTD=temp&~(1<<E); //Сигнал записи команды
  34.  
  35. temp=((lcd*16)&~(1<<RS))|(1<<E);//RS=0 –указывает на подачу команда для ЖКИ
  36. PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E
  37. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  38. PORTD=temp&~(1<<E); //Сигнал записи команды
  39.  
  40. pause(10*TIME); //Пауза для выполнения команды
  41. }
  42.  
  43. //Программа записи данных в ЖКИ
  44. void lcd_dat (unsigned char lcd)
  45. {
  46. unsigned char temp;
  47. temp=(lcd|(1<<RS))|(1<<E); //RS=1 – указывает на подачу данных для ЖКИ
  48. PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E
  49. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  50. PORTD=temp&~(1<<E); //Сигнал записи данных
  51.  
  52. temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – указывает на подачу данных для ЖКИ
  53. PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E
  54. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  55. PORTD=temp&~(1<<E); //Сигнал записи данных
  56.  
  57. pause(TIME); //Пауза для вывода данных
  58. }
  59.  
  60. //Программа иниализации ЖКИ
  61. void lcd_init (void)
  62. {
  63. lcd_com(0x2c); //фрмат данных 4-проводный интерфейс, 5x8 размер символа
  64. pause(100*TIME); //Пауза на выполнение комманды
  65. lcd_com(0x0c); //Конфигурационные данные, Показать изображение и Не показывать курсор
  66. pause(100*TIME); //Пауза на выполнение комманды
  67. lcd_com(0x01); //Очистить DDRAM и установить курсор на 0x00
  68. pause (100*TIME); //Пауза на выполнение комманды
  69. }
  70.  
  71. //Извелечения результата с АЦП
  72. unsigned int getADC(void)
  73. {
  74. unsigned int v; //перменная напряжения на АЦП
  75. v=(ADCL+ADCH*256); //Вычисление напряжения
  76. return v;
  77. }
  78.  
  79. void write_data(int u, unsigned char d)
  80. {
  81. int a;
  82. unsigned char temp;
  83.  
  84. switch (d) //Цикл переключения
  85. {
  86. case 'x' : //В случаи перменной x
  87. {
  88. //Пишем X преамбулу
  89. lcd_com(0x80); //Команда очистки экрана ЖКИ
  90. lcd_dat('x'); //Вывод на ЖКИ символа "x"
  91. lcd_dat('='); //Вывод на ЖКИ символа "="
  92. a= (u-ZERO_X)*2.56/1.024*1.25; //Вычисление вектора ускорения
  93. x=a; //Присвоение значения вектора ускорения переменной x
  94. break; //Остановка цикла переключения
  95. }
  96.  
  97. case 'y' : //В случаи переменной y
  98. {
  99. //Пишем Y преамбулу
  100. lcd_com(0x89);
  101. lcd_dat('y'); //Вывод на ЖКИ символа "y"
  102. lcd_dat('='); //Вывод на ЖКИ символа "="
  103. a= (u-ZERO_Y)*2.56/1.024*1.25; //Вычисление вектора ускорения
  104. y=a; //Присвоение значения вектора ускорения переменной y
  105. break; //Остановка цикла переключения
  106. }
  107.  
  108. case 'z' : //В случаи переменной z
  109. {
  110. //Пишем Z преамбулу
  111. lcd_com(0xc0);
  112. lcd_dat('z'); //Вывод на ЖКИ символа "z"
  113. lcd_dat('='); //Вывод на ЖКИ символа "="
  114. a= (u-ZERO_Z)*2.56/1.024*1.25; //Вычисление вектора ускорения
  115. z=a;//Присвоение значения вектора ускорения переменной z
  116. break; //Остановка цикла переключения
  117. }
  118.  
  119. default : return; //Значение по умолчанию
  120. }
  121.  
  122. if (a<0) //если вектор ускорения меньше "0"
  123. {
  124. a=-a; //Значит переменная отрицательная
  125. lcd_dat('-'); //Выводим знак минус
  126. }
  127. else //В другом случаи
  128. lcd_dat('+');//Выводим знак плюс
  129.  
  130. //Вывод данных на ЖКИ
  131. temp=a/1000;
  132. lcd_dat(0x30+temp); //Выводим данные до точки
  133. lcd_dat('.'); //Выводим точку
  134. a=a-temp*1000;
  135. temp=a/100;
  136. lcd_dat(0x30+temp); //Выводим данные после точки
  137. a=a-temp*100;
  138. temp=a/10;
  139. lcd_dat(0x30+temp); //Выводим данные после точки
  140. }
  141.  
  142. void write_full(void)
  143. {
  144. double a; //Переменная для длины вектора ускорения
  145. unsigned char temp;
  146.  
  147. a=sqrt(square(x)+square(y)+square(z));//Вычисляем длинну вектора ускорения
  148.  
  149. lcd_com (0xc9);
  150. lcd_dat ('a'); //Выводим на ЖКИ символ "а"
  151. lcd_dat ('='); //Выводим на ЖКИ символ "="
  152. if (a<0) //Если переменная "а" меньше ноля
  153. {
  154. a=-a; //Значит перменная отрицательная
  155. lcd_dat('-'); //Если минус
  156. }
  157. else lcd_dat('+'); //Если плюс
  158.  
  159. temp=a/1000; //Пишем данные
  160. lcd_dat(0x30+temp);
  161. lcd_dat('.'); //Выводим точку на ЖКИ
  162. a=a-temp*1000;
  163. temp=a/100;
  164. lcd_dat(0x30+temp);
  165. a=a-temp*100;
  166. temp=a/10;
  167. lcd_dat(0x30+temp);
  168. }
  169.  
  170. int main(void)//Основная подпрограмма
  171. {
  172. DDRD=0xfc; //Конфигурирование порта D
  173.  
  174. pause(3000); //Пауза для включения ЖКИ
  175. lcd_init(); //Инициализация ЖКИ
  176.  
  177. ADCSRA=(1<<ADEN)|(1<<ADPS1)|(1<<ADPS0);
  178. //Инициализация АЦП Делитель =/8
  179.  
  180. while(1) //Вечный цикл
  181. {
  182. ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
  183. //Конфигурирование на Внутренний источник напряжения Vref=2,56, канал PC0
  184. ADCSRA|=(1<<ADSC); //Начать преобразование
  185. while ((ADCSRA&_BV(ADIF))==0x00); //Ждем окончания преобразования
  186.  
  187. u=getADC(); //Получаем данные данные
  188. write_data(u,'x'); //Выводим данные на ЖКИ
  189.  
  190. ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(1<<MUX0);
  191. //Конфигурирование на Внутренний источник напряжения Vref=2,56, канал PC1
  192. ADCSRA|=(1<<ADSC); //Начать преобразование
  193. while ((ADCSRA&_BV(ADIF))==0x00); //Ждем окончания преобразования
  194.  
  195. u=getADC(); //Получаем данные с АЦП
  196. write_data(u,'y'); //Выводим на ЖКИ
  197.  
  198. ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(1<<MUX1)|(0<<MUX0);
  199. //Конфигурирование на Внутренний источник напряжения Vref=2,56, канал PC2
  200. ADCSRA|=(1<<ADSC); //Начать преобразование
  201. while ((ADCSRA&_BV(ADIF))==0x00); //Ждем окончания преобразования
  202.  
  203. u=getADC(); //Получаем данные с АЦП
  204. write_data(u,'z'); //Выводим на ЖКИ
  205.  
  206. write_full(); //Вывести полное ускорение
  207. pause(30000); //Пауза на выполнение команды
  208. pause(30000); //Пауза на выполнение команды
  209. }
  210. return 1;
  211. }

Как работает устройство можно посомтреть на видео:

Подумав, что скучно наблюдать мигающие циферки на дисплее, решил переписать немного прошивку так, чтобы устройство могло измерять углы наклона в 2-х перпендикулярных плоскостях, так званые углы крена и тангажа. Угол крена будем рассчитывать как arctg(y/z) а тангажа - arctg(x/z). Для этого подключим стандартный модуль math.h с нужной нам функцией double atan2(double x,double z), которая возвращает arctg(x/z), лежащий в пределах [-Pi,+Pi]. И не забудем перевести радианы в градусы, так что окончательно угол крена равен b=atan2(y,z)*180/M_PI, а тангажа a=atan2(x,z)*180/M_PI. Для того, чтобы показания не дребезжали, взял среднее арифметическое по 30-ти измерения. Также при углах крена больше +-70 градусов, показания тангажа скачут из стороны в сторону и врут, с тангажом ситуация аналогично. Потому была введена проверка корректности. То есть, если угол тангажа больше 60 градусов, то показания крена на экран не выводятся, и наоборот.

  1. #include <avr/io.h> //Стандартная библиотека ввода/вывода
  2. #include <math.h.> //Библиотека математических операций
  3.  
  4. #define RS 2 //RS=PD2
  5. #define E 3 //E=PD3
  6.  
  7. #define TIME 10
  8. //Константа временной задержки для ЖКИ
  9. //Частота тактирования 4МГц
  10.  
  11. #define ZERO_X 0x026c //Расчетная константа для координаты x
  12. #define ZERO_Y 0x0258 //Расчетная константа для координаты y
  13. #define ZERO_Z 0x029c //Расчетная константа для координаты z
  14.  
  15.  
  16. int u=0; //Напряжение на ADC
  17.  
  18. int x,y,z; //ax,ay,az
  19.  
  20. //Программа задержки
  21. void pause (unsigned int a)
  22. {
  23. unsigned int i;
  24. for(i=a;i>0;i--);
  25. }
  26.  
  27. //Программа передачи команды ЖКИ
  28. void lcd_com (unsigned char lcd)
  29. {
  30. unsigned char temp;
  31.  
  32. temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда
  33. PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E
  34. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  35. PORTD=temp&~(1<<E); //Сигнал записи команды
  36. temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда
  37. PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E
  38. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  39. PORTD=temp&~(1<<E); //Сигнал записи команды
  40. pause (10*TIME); //Пауза для выполнения команды
  41. }
  42.  
  43. //Программа записи данных в ЖКИ
  44. void lcd_dat (unsigned char lcd)
  45. {
  46. unsigned char temp;
  47. temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные
  48. PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E
  49. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  50. PORTD=temp&~(1<<E); //Сигнал записи данных
  51. temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные
  52. PORTD=temp;n//Выводим на portD младшую тетраду данных, сигналы RS, E
  53. asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации
  54. PORTD=temp&~(1<<E); //Сигнал записи данных
  55. pause(TIME); //Пауза для вывода данных
  56. }
  57.  
  58. void lcd_init (void)//Иниализация ЖКИ
  59. {
  60. lcd_com(0x2c); //4-проводный интерфейс, 5x8 размер символа
  61. pause(100*TIME);
  62. lcd_com(0x0c); //Показать изображение, курсор не показывать
  63. pause(100*TIME);
  64. lcd_com(0x01); //Очистить DDRAM и установить курсор на 0x00
  65. pause (100*TIME);
  66. }
  67.  
  68. unsigned int getADC(void) //Извелечения результата с АЦП
  69. {
  70. unsigned int v;
  71. v=(ADCL+ADCH*256);
  72. return v;
  73. }
  74.  
  75. void write_full(int x, int y, int z)
  76. {
  77. double a,b;
  78. unsigned char temp;
  79.  
  80. a=atan2(x,z)*180/M_PI;//Вычисляем углы
  81. b=atan2(y,z)*180/M_PI;
  82.  
  83. lcd_com (0x80); //Пишем "тангаж"
  84. lcd_dat (0xbf);
  85. lcd_dat (0x61);
  86. lcd_dat (0xbd);
  87. lcd_dat (0xb4);
  88. lcd_dat (0x61);
  89. lcd_dat (0xb6);
  90. lcd_dat ('=');
  91.  
  92. if (a_valid==1)
  93. {
  94. if (a<0)
  95. {//Пишем знак
  96. a=-a;
  97. lcd_dat('-');
  98. }
  99. else lcd_dat('+');
  100.  
  101. temp=a/100; //Пишем данные
  102. a=a-temp*100;
  103. lcd_dat(0x30+temp);
  104. temp=a/10;
  105. a=a-temp*10;
  106. lcd_dat(0x30+temp);
  107. lcd_dat(0x30+a);
  108. lcd_dat(0xdf);
  109. }
  110. else
  111. {
  112. lcd_dat('N');
  113. lcd_dat('/');
  114. lcd_dat('a');
  115. lcd_dat(' ');
  116. lcd_dat(' ');
  117. }
  118. lcd_com (0xc0);//Пишем "крен"
  119. lcd_dat (0xba);
  120. lcd_dat (0x70);
  121. lcd_dat (0x65);
  122. lcd_dat (0xbd);
  123. lcd_dat ('=');
  124. if (b_valid==1)
  125. {
  126. if (b<0) { //Пишем знак
  127. b=-b;
  128. lcd_dat('-');
  129. }
  130. else lcd_dat('+');
  131.  
  132. temp=b/100; //Пишем данные
  133. b=b-temp*100;
  134. lcd_dat(0x30+temp);
  135. temp=b/10;
  136. b=b-temp*10;
  137. lcd_dat(0x30+temp);
  138. lcd_dat(0x30+b);
  139. lcd_dat(0xdf);
  140. }
  141. else {
  142. lcd_dat('N');
  143. lcd_dat('/');
  144. lcd_dat('a');
  145. lcd_dat(' ');
  146. lcd_dat(' ');
  147. }
  148. }
  149.  
  150. int abs (int x)
  151. {
  152. if (x>=0) return x;
  153. else return -x;
  154. }
  155.  
  156. int main(void)
  157. { unsigned char i;
  158. DDRD=0xfc;
  159.  
  160. pause(3000); //Пауза для включения ЖКИ
  161. lcd_init(); //Инициализация ЖКИ
  162.  
  163.  
  164. ADCSRA=(1<<ADEN)|(1<<ADPS1)|(1<<ADPS0); //Включить АЦП, прескаллер =/8
  165. while(1)
  166. {
  167. x=y=z=0;
  168.  
  169. for (i=0;i<30;i++)
  170. {
  171. ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);//Внутренний Vref=2,56, канал PC0
  172. ADCSRA|=(1<<ADSC); //Начать преобразование
  173. while ((ADCSRA&_BV(ADIF))==0x00) //Ждем окончания преобразования
  174. ;
  175.  
  176. u=getADC(); //Считать напряжение
  177. x= x+(u-ZERO_X)*2.56/10.24*1.25; //Добавить в сумму x
  178.  
  179. ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(1<<MUX0);//Внутренний Vref=2,56, канал PC1
  180. ADCSRA|=(1<<ADSC); //Начать преобразование
  181. while ((ADCSRA&_BV(ADIF))==0x00) //Ждем окончания преобразования
  182. ;
  183.  
  184. u=getADC(); //Считать напряжение
  185. y= y+(u-ZERO_Y)*2.56/10.24*1.25; //Добавить в сумму y
  186.  
  187. ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(1<<MUX1)|(0<<MUX0);//Внутренний Vref=2,56, канал PC2
  188. ADCSRA|=(1<<ADSC); //Начать преобразование
  189. while ((ADCSRA&_BV(ADIF))==0x00) //Ждем окончания преобразования
  190. ;
  191.  
  192. u=getADC(); //Считать напряжение
  193. z= z+(u-ZERO_Z)*2.56/10.24*1.25; //Добавить в сумму z
  194.  
  195. }
  196. a_valid=b_valid=1;
  197. if ((abs(x/30)>85)&&(abs(y/30)<30)) { //Вычисляем корректность данных
  198. a_valid=1;
  199. b_valid=0;
  200. }
  201. if ((abs(y/30)>85)&&(abs(x/30)<30)) {
  202. a_valid=0;
  203. b_valid=1;
  204. }
  205. write_full (x,y,z); //Выводим результат на ЖКИ
  206. pause(15000);
  207. }
  208.  
  209. return 1;
  210. }

Работа этого макета уже более интересна, ее можно посмотреть на видео ниже:

После всего этого я поискал в Google похожие проекты и узрел идею простенькой игрушки: по дисплею катается шарик оставляя за собой след, управлять которым можно с помощью наклона макетки с акселерометром, как только шарик врежется в бортик – игра закончена, можно конечно и выиграть, набрав 9999 очков. Очки насчитываются по продолжительности игры. Можно конечно схитрить, положить платку на ровную площадку, чтобы шарик не двигался, и дождаться выигрыша, но это не спортивно :).
Так как на символьном ЖКИ шарик не покатаешь, то подключил графический ЖКИ WG12864A .

Источник тактирования – внутренний RC генератор на 1 МГц. Конденсаторы С1,С2,С3,С4,С6,С9,С11 – керамические на 0,1мкФ, С10 – керамический на 1мкФ, С8 – танталовый на 68мкФ, С5,С7 – электролиты, на 100 и 200мкФ соответственно. Резисторы R4,R5,R6,R7,R9 по 1кОм, R1 – 10кОм, R10 – 17Ом, потенциометр VR2 – на 10кОм. D2 – слаботочный светодиод для индикация работы схемы.
Код игрушки кривоват из-за того, что некривой код не влез в память mega8, как по использованию памяти программ, так и по оперативной памяти (я не использовал оптимизацию). Его можно легко причесать, если использовать контроллер с большим количеством памяти на борту, например микроконтроллер ATmega16 или включив оптимизацию, но придется переделать подпрограмму генерации задержки.
Понаблюдать за процессом игры можно здесь:

Скачать архив со всеми 3-мя прошивками в формате AVR Studio 4 + печатная плата в формате .lay для программы Sprint layout 5

Скажите пож.,

А что за 1.25 в этой формуле a= (u-ZERO_X)*2.56/1.024*1.25?? откуда она берется?чет не могу понять?

А каким образом

А каким образом рассчитывались переменные ZERO_x,ZERO_y,ZERO_z? откуда они брались? Спасибо за ответ...

скажите плиз, собрал данную

скажите плиз, собрал данную схему, прошил флеш МК - проблема в том что дисплей не все отображает, работает половина дисплея и тускновато чет. в чем может быть прооблема?

Сам дисплей првоерял?

Сам дисплей проверял? С другой программой работает норм?
Попробуй вывести на него все точки что есть на экране, если проблема в дисплее будет то все сразу станет видно. Но насчет половины думаю что проблема больше в контроллере дисплея. Их там кстати какраз два стоит и каждый своей половиной управляет. Возможно один из них вылетел.

да, дело было в дисплее,

да, дело было в дисплее, слетел один контроллер слетел. поставил другой все ок)!

Скажите плиз,я не спец в

Скажите плиз,я не спец в этом, начинаю только - вопрос по схеме заземления которые есть на схеме соединяются между собой??? и питание 5Вк 5В, 3В к 3В соответственно?

Да именно так. Точки питания

Да именно так.
Точки питания с обозначениями +5В соединяются вместе и подключаются к +5Вольт источника питания.
+3,3В соединяются вместе и подключаются к точке +3Вольта источника питания.
Не подай только 5 Вольт вместо 3,3 Вольта, СГОРИТ!

А что-то вроде джойстика из

А что-то вроде джойстика из этого замутить можно?

Конечно, сейчас акселерометры

Конечно, сейчас акселерометры в моднявые джойстики ставят

надо было совместить этот

надо было совместить этот проект с графическим индикатором. датчик поместить в машину, и на индикаторе рисовать наклон машинки и угол в градусах, и при достижении критических значений пищать мерзким сигналом - кажется, так делается на разных джыпах - чтобы знать, когда можно опасаться что опрокинешься)))

по теме - любопытно, каким образом в домашних условиях паять такие крошечные устройства...

машины нету :) как куплю -

машины нету :) как куплю - так сразу и сделаю

Другие акселерометры

У меня в распоряжении акселерометры LIS302DL. Как сильно изменится схема и программа?

Судя по datasheet твой

Судя по datasheet твой акселерометр выдает не аналоговый сигнал (в нашем случаи напряжение до 3Вольт) а цифровой по протоколу I2C.
Соответственно схема кардинально поменяется и программа соответственно тоже.

LIS302DL

Спасибо за ответ.
Третий день уже никак в Интернете не могу найти аналогичную схему, но на LIS302DL.
Может быть Вы что нибудь подобное видели?

Готового проекта под LIS302DL

Готового проекта под LIS302DL не видел. В LIS302DL еще есть SPI интерфейс. Думаю заставить его работать будет не сложно.
Подключаем к МК:
схема подключения LIS302DL
Если планируем юзать i2c, то вывод CS на +3В, SDO (который 12-й) не подключаем. Vdd_io соединяем с Vdd или с +5В, если у нас МК питается от 5-ти вольт.
По i2c периодически снимаем данные и все)
Немного про i2c я уже писа: Шина I2C и микроконтроллер AVR пример, PCF8583 вечный календарь.

ИМХО с SPI будет проще разобраться, если новичек. Так что советую на SPI сделать.

Я бы делал так:

Я бы делал так:
1. Скачал бы datasheet. Почитал бы каким образом работает это устройство. Посмотрел бы типовую схему включения. Посмотрел бы пример опроса датчика или получения с него информации.
2. Прочитал бы статью, на тему работа с программным I2C.
3. Нарисовал бы схему с учетом статьи выше, с применением микроконтроллера Atmega8 или старше (так как более ранние МК не имеют возможности реализовать программный I2C).
4. Экспериментировал бы во всю!