Useful Mobile Apps
         




Подключиться к YouTube?




youtu.be/q2DXLZFgrfU





Подключиться к YouTube?




youtu.be/HlSLG57gGIM





Подключиться к YouTube?




youtu.be/ssCKAI_0RQ4





Подключиться к YouTube?




youtu.be/ZXCubHc8mQU





Подключиться к YouTube?




youtu.be/zcg7SMxou7A





Подключиться к YouTube?




youtu.be/0LeZEhgOXYU

Bluetooth-акселерометр



Bluetooth-акселерометр делается на основе платформы Arduino Nano, модуля акселерометра ADXL335 и bluetooth-модуля HM-10 поддерживающего Bluetooth 4.0 LE (НЕЛЬЗЯ использовать модули HC-06, HC-05).

Даже если Вы никогда не слышали об Arduino, то это будет отличный повод с ней познакомиться. Здесь не будет подробного описания Arduino, но в Интернете про это есть огромное количество информации, и на наиболее важную информацию будут ссылки.

Главным преимуществом Bluetooth по сравнению с Wi-Fi является очень маленькое потребление энергии. Однако Bluetooth-модуль имеет очень маленькую скорость передачи дынных, и поэтому нужно тщательно оптимизировать передаваемые данные. Сжатие данных основывается на расчете разницы между соседними значениями и передаче по Bluetooth только этой разницы. Благодаря этому для передачи значения хватает одного байта. Это позволяет обеспечить максимальную частоту дискретизации около 1870 Hz (при измерении 1 оси).

Преимущества подключения акселерометра через bluetooth в сравнении с подключением через гнездо для наушников:

• Измерение не только колебаний но и абсолютных значений.
• Нет минимального значения частоты дискретизации. Больше подходит для измерения колебаний с низкой частотой (< 15 Hz).
• Удаленное подключение.
• 3 оси.
• Можно подключить акселерометр с цифровым выходом (BMA180, ADXL345, MPU6050, LSM9DS1).

Недостатки:

• Чувствительность меньше (к цифровым акселерометрам (BMA180, LSM9DS1) это не относится). Может быть увеличена в 100 раз.
• Максимальная частота дискретизации меньше.


Подключение Arduino Nano к компьютеру и загрузка скетча

Download the Arduino IDE
Getting Started with the Arduino Desktop IDE
Getting Started with the Arduino Nano
Install the Arduino Software (IDE) on OS X
Foundations
Language Reference

Скетч 1:

///////////////////////////////
// © 2017 Dmitriy Kharutskiy //
///////////////////////////////

byte ByteArr[20];
int i = 0;
int ii = 0;
int AccelValue = 0;
int LastAccelValue = 0;
int dValue = 0;

void setup()
{
	//Put your setup code here, to run once:
		
	//Открывает последовательный порт, устанавливает скорость передачи данных.
	Serial.begin(9600);
	//Serial.begin(115200); 
    
	//A5 => Высокоимпедансное состояние
	pinMode(A5, INPUT);
	digitalWrite(A5, LOW);
	//A5 => (+)
	//pinMode(A5, OUTPUT);
	//digitalWrite(A5, HIGH);
		
	//A1 => GND   
	pinMode(A1, OUTPUT);
	digitalWrite(A1, LOW);
		
	//A0 => Высокоимпедансное состояние
	//pinMode(A0, INPUT);
	//digitalWrite(A0, LOW);
		
	//Настраивает опорное напряжение, используемое для аналогового входа.
	analogReference(EXTERNAL); //EXTERNAL: Напряжение подаваемое на вывод AREF (только 0-5 В) используется как опорное напряжение.

	//D4 => (+)
	pinMode(4, OUTPUT); 
	digitalWrite(4, HIGH);
		
	//D5 => GND
	pinMode(5, OUTPUT); 
	digitalWrite(5, LOW);

	delay(500); //Пауза в миллисекундах.
}

void loop() 
{
	//Put your main code here, to run repeatedly:

	AccelValue = analogRead(A3); //Напряжение поданное на аналоговый вход (от 0В до опорного напряжения) будет преобразовано в значение от 0 до 1023.
	
	if (i < 3)
	{
		ByteArr[ii] = char(-128);
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue);
	}
	else
	{
		dValue = AccelValue - LastAccelValue;
		if (abs(dValue) > 127)
		{
			ByteArr[ii] = char(-128);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue);
		}
		else
		{
			ByteArr[ii] = char(dValue);
		}
	}
	LastAccelValue = AccelValue;
    
	i++;
	ii++;
	WriteFunction();

	//delay(3); //~319 Hz.
	delayMicroseconds(1000); //~880 Hz. MAX для Serial.begin(9600). delayMicroseconds(1000) = delay(1)
	//delayMicroseconds(400); //Serial.begin(115200), ~1867 Hz. MAX  
}

void WriteFunction()
{
	if (ii == 20) 
	{
		Serial.write(ByteArr, ii);
		ii = 0;
	}
  
	if (i >= 200)
	{
		i = 0;
	}
}



При загрузке скетча через USB, пины TXD и RXD должны быть свободны.

Если ваш модуль акселерометра отличается от моего и у него контакты расположены по другому, то в скетче нужно изменить номера пинов Arduino Nano.


Сборка bluetooth-акселерометра








Соединения:

Arduino Nano и HM-10 модуль
D4 < − − − > VCC
D5 < − − − > GND
TXD < − − − > RXD
RXD < − − − > TXD

Arduino Nano и ADXL335 модуль
A2 < − − − > Z
A4 < − − − > GND

ADXL335 модуль
+4.5 V < − − − > 5K < − − − > VCC

Arduino Nano
+4.5 V < − − − > 5V
0 V < − − − > GND
+4.5 V < − − − > 5K < − − − > REF
REF < − − − > 5K < − − − > 0 V

Цифровые выводы
Функция digitalWrite()
Высокоимпедансное состояние
Аналоговые входы
Функция analogRead()
Опорное напряжение
Arduino Nano - A6/A7
Делитель напряжения

Модуль акселерометра ADXL335 снабжен стабилизатором напряжения. При подключении к нему напряжения больше 3.6 V, стабилизатор напряжения начинает создавать шумы видимые в результатах измерений.

Чтобы уменьшить напряжение на акселерометре, он должен подключаться к 4.5 V через резистор. При подключении акселерометра к пину "3V3", в измерениях тоже видны шумы.


Шумы от стабилизатора напряжения.
Могут быть более значительные шумы от bluetooth-модуля.
Про них читайте ниже.


Подключение 4.5 V через резистор.

Для тестирования, в настройках указаны такие значения, чтобы показывались величины получаемые от аналогово-цифрового преобразователя (без пересчета в вольты или ускорение).

Для увеличения чувствительности аналогового входа, опорное напряжение делается в два раза меньше чем напряжение питания. Делается это делителем напряжения из двух одинаковых резисторов. Опорное напряжение подключается к пину "REF".

Обратите внимание чтобы ножки резисторов ни при каких обстоятельствах не могли коснуться друг друга.

Вставлять резисторы удобно с помощью плоскогубцев.


Настройка приложения

1:

Правильность настройки частоты дискретизации нужно обязательно проверить. Для этого нужен источник вибрации с известной частотой.

2:

Vref = V × R2 / (R1 + R2)

На пине "AREF" имеется внутренний резистор 32 kOhm.

R2 = 5K × 32K / (5K + 32K) = 4.32K Ohm

Напряжение батареек в процессе работы постоянно уменьшается. Поэтому лучше измерить напряжение (под нагрузкой) мультиметром. Если напряжение (под нагрузкой) одной батарейки 1.4 V, тогда суммарное напряжение 4.2 V.

Vref = 4.2 × 4.32K / (5K + 4.32K) = 1.947 V

3 и 4:


Preliminary Technical Data ADXL335

Напряжение на акселерометре при подключении через резистор 5K Ohm примерно равно V × 0.7 (например 4.2 × 0.7 = 2. 94).

Правильность настроек можно проверить и уточнить сделав эксперименты при отключенном режиме "Только вибрация". Значение от оси направленной строго вниз должно быть -1g, а при переворачивании акселерометра должно быть +1g.

Без мультиметра сделать это сложно, из-за необходимости одновременного настраивания опорного напряжения и чувствительности акселерометра. Вначале нужно сделать так чтобы разница между максимумом и минимумом была около 2g. Потом регулируется напряжение для 0g.


Настройка bluetooth-модуля HM-10 для увеличения скорости передачи данных

Bluetooth-модуль можно подключить к компьютеру через адаптер USB-UART. Однако это дополнительные траты и возможные лишние действия для поиска и установки драйверов. Bluetooth-модуль можно настроить и через Arduino Nano.

Однако изменять скорость передачи данных можно только до 115200 bps , потому что SoftwareSerial не поддерживает скорость 230400 bps.

Тем более что при скорости 230400 bps не наблюдается реального увеличения скорости по сравнению с 115200 bps. И к сожалению SoftwareSerial не получается использовать при работе bluetooth-акселерометра (если частота дискретизации больше 500 Hz), потому что отправка данных через SoftwareSerial останавливает главную программу примерно на 2 мс.

SoftwareSerial Library
Software Serial Example
SoftwareSerial

Скетч 2:

#include <SoftwareSerial.h> //Подключаем библиотеку SoftwareSerial

SoftwareSerial softSerial(11, 12); //Создаём объект softSerial указывая выводы RX, TX. В данном случае вывод TX модуля подключается к выводу 11 Arduino, а вывод RX модуля к выводу 12 Arduino.

void setup()
{
	//Инициируем работу шин UART с указанием скоростей обеих шин:    
	//softSerial.begin(115200);
	softSerial.begin(9600);    
	//Serial.begin(115200); 
	Serial.begin(9600);

	//D9 => (+)
	pinMode(9, OUTPUT); 
	digitalWrite(9, HIGH);
    
	//D10 => GND
	pinMode(10, OUTPUT); 
	digitalWrite(10, LOW);
}

void loop()
{
	//Выполняем ретрансляцию. Всё что пришло с модуля - отправляем компьютеру, а всё что пришло с компьютера - отправляем модулю.
	if (softSerial.available()) Serial.write(softSerial.read()); //От модуля через Arduino к компьютеру.
	if (Serial.available()) softSerial.write(Serial.read()); //От компьютера через Arduino к модулю.
}





Проверка работы монитора: AT


Список всех команд: AT+HELP


Получение версии прошивки и версии Bluetooth: AT+VERSION


Настройка скорости передачи данных: AT+BAUD (AT+BAUD8 => 115200 bps, AT+BAUD4 => 9600 bps)


Изменения в скетче 1:

. . .

void setup()
{
	
	. . .
	
	//Serial.begin(9600);
	Serial.begin(115200);
	
	. . .
	
}

void loop()
{	
	
	. . .
	
	//delay(3); //~319 Hz.
	//delayMicroseconds(1000); //~880 Hz. MAX для Serial.begin(9600). delayMicroseconds(1000) = delay(1)
	delayMicroseconds(400); //Serial.begin(115200), ~1867 Hz. MAX  
}

. . .



Увеличение/уменьшение чувствительности Arduino Nano

Для изменения чувствительности акселерометра (аналогового входа) меняется опорное напряжение на пине "REF". Если опорное напряжение будет слишком большое, то вместо синусоиды буду ступеньки. Кроме того очень маленькие изменения не будут фиксироваться.

Если опорное напряжение будет слишком маленькое, то напряжение измеряемого сигнала может превысить опорное напряжение и тогда результат измерения будет соответствовать опорному напряжению.

Если разница между соседними величинами будет превышать 10% (5% при дополнительном использовании лазерного датчика) от опорного напряжения, то разница между соседними измерениями не будет помещаться в байт и передача данных по bluetooth будет работать нестабильно. В этом случае можно уменьшить частоту дискретизации (увеличить паузу между измерениями).


Другие варианты сборки

Bluetooth-модуль в момент отправки данных потребляет больше тока. Это может привести к небольшому снижению напряжения во всем устройстве. Вследствие этого уменьшается и опорное напряжение. Это приводит к искажению результатов измерения. Чем меньше батарейки и чем хуже они подключены, тем больше будут искажения. Чтобы этого избежать, нужно подключить к bluetooth-модулю конденсатор (~220 mkF).


Шумы от bluetooth-модуля.



С конденсатором 220 mkF.

Но при включении питания происходит быстрая зарядка конденсатора, при этом сила тока может превышать допустимые значения для пина. И чем больше емкость конденсатора тем больше вероятность что через какое то время пин сгорит. Поэтому питание к bluetooth-модулю лучше подсоединить напрямую от батареек. Но для эффективной работы конденсатора нужно между конденсатором и плюсом питания добавить резистор (~51 Ohm). При этом чем больше емкость конденсатора или сопротивление резистора, тем лучше будет фильтр. Однако при слишком большом сопротивлении резистора, bluetooth-модулю будет не хватать напряжения (особенно если источник пинания имеет напряжение 3.6 V и ниже). Также очень важно состояние контактов конденсатора с макетной платой, и иногда конденсатор нужно вытащить из макетной платы и вставить обратно. Чтобы убрать шумы иногда нужно обновить контакты подключающие батарейки, для этого нужно оба провода вытащить и вставить обратно. Лучшем вариантом избавления от шумов будет соединение деталей пайкой на специальной макетной плате.


Изменения в скетче 1:

. . .

void setup()
{
	
	. . .
	
	//A5 => Высокоимпедансное состояние
	//pinMode(A5, INPUT);
	//digitalWrite(A5, LOW);
	//A5 => (+)
	pinMode(A5, OUTPUT);
	digitalWrite(A5, HIGH);

	. . .

	//D4 => (+)
	//pinMode(4, OUTPUT); 
	//digitalWrite(4, HIGH);
		
	//D5 => GND
	//pinMode(5, OUTPUT); 
	//digitalWrite(5, LOW);
	
	. . .
	
}

. . .


Если батарейка выступает из батарейного отсека, чтобы устройство стояло ровно, можно приклеить мягкий материал.

Если размер устройства не имеет большого значения, то лучше использовать вместо батареек AAA батарейки AA с соответствующим батарейным отсеком. Батарейки AA будут лучше отдавать ток в моменты передачи данных, и у них будет меньше колебаться напряжение под нагрузкой.

Если требуется максимально облегчить или уменьшить размер устройства, можно использовать литиевую батарейку с напряжением 3.6 V.


Самая дорогая часть в этом варианте - это литиевая батарейка. Поэтому используйте этот вариант в крайнем случае. Устройство потребляет около 20 mA, а емкость батарейки (по словам продавца) около 1600 mAh, следовательно такой батарейки должно хватить примерно на трое суток непрерывной работы. Поэтому вместо батарейки размером 2/3AA можно использовать 1/2AA. Ножки батарейки конечно же можно подключить к пинам "5V" и "GND" без дополнительных проводов, но тогда будет труднее отключать питание и ножки батарейки могут быстро отломаться.

Чтобы батарейка не колебалась на ножках внося помехи и результаты измерений, вставлен кусочек мягкого материала.


Лазерный датчик

Лазерный датчик позволяет определить смещение центра масс вращающейся детали.

Максимальная частота, при которой можно примерно определить фазу метки, около 50 Hz. Только ради этой функции не нужно собирать bluetooth-акселерометр. Стробоскоп для акселерометра точнее и проще в изготовлении. Однако лазерный датчик не имеет нижней границы частоты вращения, поэтому если частота вращения меньше 15 Hz, нужно использовать лазерный датчик а не стробоскоп.



Соединения:

Лазерный датчик
+4.5 V < − − − > 5K < − − − > (Collector) 3DU5C (Emitter) < − − − > 5K < − − − > 0 V

Перед использованием лазерного датчика его нужно протестировать. Для этого лазерный датчик подключается вместо ADXL335 акселерометра.



Лазерный датчик и Arduino Nano
Фототранзистор 3DU5C (Emitter) < − − − > A3

Если на датчик будет светить свет от лампы подключенной к сети 220V или 110V, то могут наблюдаться колебания с частотой равной частоте сети умноженной на 2. Так можно проверять правильность настройки частоты дискретизации.



Теперь можно наклеить на вентилятор полоску белой клейкой ленты и направить лазерный датчик на вращающийся вентилятор.


Обратите внимание, что для стабильной передачи данных по bluetooth, нужно чтобы разница между соседними значениями была меньше 128. При работе лазерного датчика вместе с акселерометром, разница между соседними значениями не важна.

После проверки лазерного датчика можно собирать следующую схему.



Лазерный датчик и Arduino Nano
Фототранзистор 3DU5C (Emitter) < − − − > A6

В Arduino Nano нужно загрузить другой скетч.

При загрузке скетча через USB, пины TXD и RXD должны быть свободны.

Скетч 3:

///////////////////////////////
// © 2017 Dmitriy Kharutskiy //
///////////////////////////////

byte ByteArr[20];
int i = 0;
int ii = 0;
int AccelValue = 0;
int LastAccelValue = 0;
int dValue = 0;
int LaserValue = 0;
int maxLaserValue = 0;
int minLaserValue = 1023;
int iii = 0;
int Border = 0;
boolean Mark = false;

void setup() 
{
	//Put your setup code here, to run once:
  
	//Открывает последовательный порт, устанавливает скорость передачи данных.
	Serial.begin(115200); 
	
	//A5 => Высокоимпедансное состояние
	pinMode(A5, INPUT);
	digitalWrite(A5, LOW);
	//A5 => (+)
	//pinMode(A5, OUTPUT);
	//digitalWrite(A5, HIGH);
		
	//A1 => GND   
	pinMode(A1, OUTPUT);
	digitalWrite(A1, LOW);
		
	//A0 => Высокоимпедансное состояние
	//pinMode(A0, INPUT);
	//digitalWrite(A0, LOW);
		
	//Настраивает опорное напряжение, используемое для аналогового входа.
	analogReference(EXTERNAL); //EXTERNAL: Напряжение подаваемое на вывод AREF (только 0-5 В) используется как опорное напряжение.

	//D4 => (+)
	pinMode(4, OUTPUT); 
	digitalWrite(4, HIGH);
		
	//D5 => GND
	pinMode(5, OUTPUT); 
	digitalWrite(5, LOW);

	delay(500); //Пауза в миллисекундах.
}

void loop() 
{
	//Put your main code here, to run repeatedly:

	AccelValue = analogRead(A3); //Напряжение поданное на аналоговый вход (от 0В до опорного напряжения) будет преобразовано в значение от 0 до 1023.
	LaserValue = analogRead(A6);		
	
	iii++;
	if (LaserValue > maxLaserValue) maxLaserValue = LaserValue;
	if (LaserValue < minLaserValue) minLaserValue = LaserValue;
	if (iii > 2000)
	{
		Border = maxLaserValue - round((maxLaserValue - minLaserValue) / 2.0);
		iii = 0;
		maxLaserValue = 0;
		minLaserValue = 1023;
	}
	Mark = (Border > 0 && LaserValue > Border);

	if (i < 3)
	{
		ByteArr[ii] = char(-128);
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue);
	}
	else
	{
		dValue = AccelValue - LastAccelValue;
		if (abs(dValue) > 63)
		{
			ByteArr[ii] = char(-128);
			i++;
			ii++;
			WriteFunction();	
			
			ByteArr[ii] = highByte(AccelValue);			
			i++;
			ii++;
			WriteFunction();
			
			ByteArr[ii] = lowByte(AccelValue);
		}
		else
		{
			ByteArr[ii] = char(dValue);
			
			if (Mark)
			{
				if (dValue >= 0) bitWrite(ByteArr[ii], 6, 1);
				else bitWrite(ByteArr[ii], 6, 0);
			}
		}
	}
	LastAccelValue = AccelValue;
    
	i++;
	ii++;
	WriteFunction();
  
	//delayMicroseconds(400); // ~1540 Hz
	delayMicroseconds(280); // ~1893 Hz
}

void WriteFunction()
{
	if (ii == 20) 
	{
		Serial.write(ByteArr, ii);
		ii = 0;
	}
	
	if (i >= 200)
	{
		i = 0;
	}
}


С загруженным в Arduino Nano скетчем для лазерного датчика, в настройках приложения обязательно должна быть включена опция "Лазерный датчик". Частота дискретизации должна быть максимальной (около 1890 Hz).

Из-за наличия в конструкции модуля акселерометра RC-цепи, происходит сдвиг фазы сигнала. Для компенсации этого сдвига можно указать значение произведения значений резистора (kOhm) и конденсатора (nF). Например, 32 kOhm × 100 nF = 3200.

Учитывайте что RC-цепь акселерометра уменьшает или совсем сглаживает колебания с большой частотой.


Увеличение чувствительности акселерометра

Используя операционные усилители соединенные в схему ДИФФЕРЕНЦИАЛЬНОГО усилителя, можно усилить ПОЛЕЗНУЮ часть сигнала в 100-1000 раз (и больше). На видео сигнал от акселерометра увеличен в 50 раз. При этом хорошо видны шумы акселерометра. Инструментальный усилитель AD623 - это готовая схема дифференциального усилителя составленная из трех операционных усилителей. БОльшая часть электронных компонентов на схеме ниже нужны только для уменьшения помех.









1:

Чувствительность акселерометра = Исходная чувствительность
акселерометра × (1 + 100/Rg(kOhm))
Например: 300 × (1 + 100/2.08) = 14730 mV/g

2:

Для удобства настройки V2, лучше всего записать это значение равным 0. Но если есть необходимость видеть абсолютные значения, тогда нужно измерить V2 и сделать расчет:

Напряжение при нулевом ускорении = (V0 - V2) × K
V0 - Исходное напряжение при нулевом ускорении
K = 1 + 100/Rg(kOhm)


Трехосевой Bluetooth-акселерометр

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

Скетч 4 (XYZ):

///////////////////////////////
// © 2017 Dmitriy Kharutskiy //
///////////////////////////////

byte ByteArr[20];
int i = 0;
int ii = 0;
int AccelValue1 = 0;
int AccelValue2 = 0;
int AccelValue3 = 0;
int LastAccelValue1 = 0;
int LastAccelValue2 = 0;
int LastAccelValue3 = 0;
int dValue1 = 0;
int dValue2 = 0;
int dValue3 = 0;

void setup()
{
	//Put your setup code here, to run once:
		
	//Opens serial port, sets data rate.
	Serial.begin(9600);
	//Serial.begin(115200); 
    
	//A5 => High impedance
	pinMode(A5, INPUT);
	digitalWrite(A5, LOW);
	//A5 => (+)
	//pinMode(A5, OUTPUT);
	//digitalWrite(A5, HIGH);
		
	//A1 => GND   
	pinMode(A1, OUTPUT);
	digitalWrite(A1, LOW);
		
	//A0 => High impedance
	//pinMode(A0, INPUT);
	//digitalWrite(A0, LOW);
		
	//Configures the reference voltage used for analog input (i.e. the value used as the top of the input range).
	analogReference(EXTERNAL); //EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference.

	//D4 => (+)
	pinMode(4, OUTPUT); 
	digitalWrite(4, HIGH);
		
	//D5 => GND
	pinMode(5, OUTPUT); 
	digitalWrite(5, LOW);

	delay(500); //Pauses the program for the amount of time (in miliseconds) specified as parameter.
}

void loop() 
{
	//Put your main code here, to run repeatedly:

	AccelValue1 = analogRead(A4); //X-axis. Reads the value from the specified analog pin. This means that it will map input voltages between 0V and reference voltage into integer values between 0 and 1023.
	AccelValue2 = analogRead(A3); //Y-axis.
	AccelValue3 = analogRead(A2); //Z-axis.
  
	if (i < 7)
	{
		ByteArr[ii] = char(-128);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue1);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue1);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue2);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue2);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue3);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue3);
	}
	else
	{
		dValue1 = AccelValue1 - LastAccelValue1;
		dValue2 = AccelValue2 - LastAccelValue2;
		dValue3 = AccelValue3 - LastAccelValue3;
		
		if (abs(dValue1) > 127 || abs(dValue2) > 127 || abs(dValue3) > 127)
		{
			ByteArr[ii] = char(-128);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue2);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue2);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue3);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue3);
		}
		else
		{
			ByteArr[ii] = char(dValue1);			
			i++;
			ii++;
			WriteFunction();
			
			ByteArr[ii] = char(dValue2);			
			i++;
			ii++;
			WriteFunction();
			
			ByteArr[ii] = char(dValue3);
		}
	}
	LastAccelValue1 = AccelValue1;
	LastAccelValue2 = AccelValue2;
	LastAccelValue3 = AccelValue3;
    
	i++;
	ii++;
	WriteFunction();

	delay(3); //~293 Hz. MAX for Serial.begin(9600).
	//delayMicroseconds(1200); //Serial.begin(115200), ~622 Hz. MAX    
}

void WriteFunction()
{
	if (ii == 20) 
	{
		Serial.write(ByteArr, ii);
		ii = 0;
	}
  
	if (i >= 600)
	{
		i = 0;
	}
}


Скетч 5 (XY):

///////////////////////////////
// © 2017 Dmitriy Kharutskiy //
///////////////////////////////

byte ByteArr[20];
int i = 0;
int ii = 0;
int AccelValue1 = 0;
int AccelValue2 = 0;
int LastAccelValue1 = 0;
int LastAccelValue2 = 0;
int dValue1 = 0;
int dValue2 = 0;

void setup()
{
	//Put your setup code here, to run once:
		
	//Opens serial port, sets data rate.
	Serial.begin(9600);
	//Serial.begin(115200); 
    
	//A5 => High impedance
	pinMode(A5, INPUT);
	digitalWrite(A5, LOW);
	//A5 => (+)
	//pinMode(A5, OUTPUT);
	//digitalWrite(A5, HIGH);
		
	//A1 => GND   
	pinMode(A1, OUTPUT);
	digitalWrite(A1, LOW);
		
	//A0 => High impedance
	//pinMode(A0, INPUT);
	//digitalWrite(A0, LOW);
		
	//Configures the reference voltage used for analog input (i.e. the value used as the top of the input range).
	analogReference(EXTERNAL); //EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference.

	//D4 => (+)
	pinMode(4, OUTPUT); 
	digitalWrite(4, HIGH);
		
	//D5 => GND
	pinMode(5, OUTPUT); 
	digitalWrite(5, LOW);

	delay(500); //Pauses the program for the amount of time (in miliseconds) specified as parameter.
}

void loop() 
{
	//Put your main code here, to run repeatedly:

	AccelValue1 = analogRead(A4); //X-axis. Reads the value from the specified analog pin. This means that it will map input voltages between 0V and reference voltage into integer values between 0 and 1023.
	AccelValue2 = analogRead(A3); //Y-axis.
  
	if (i < 5)
	{
		ByteArr[ii] = char(-128);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue1);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue1);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue2);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue2);
	}
	else
	{
		dValue1 = AccelValue1 - LastAccelValue1;
		dValue2 = AccelValue2 - LastAccelValue2;
		
		if (abs(dValue1) > 127 || abs(dValue2) > 127)
		{
			ByteArr[ii] = char(-128);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue2);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue2);
		}
		else
		{
			ByteArr[ii] = char(dValue1);			
			i++;
			ii++;
			WriteFunction();
			
			ByteArr[ii] = char(dValue2);			
		}
	}
	LastAccelValue1 = AccelValue1;
	LastAccelValue2 = AccelValue2;
    
	i++;
	ii++;
	WriteFunction();

	delay(2); //~440 Hz. MAX для Serial.begin(9600).
	//delayMicroseconds(800); //Serial.begin(115200), ~934 Hz. MAX
}

void WriteFunction()
{
	if (ii == 20) 
	{
		Serial.write(ByteArr, ii);
		ii = 0;
	}
  
	if (i >= 400)
	{
		i = 0;
	}
}



Подключение акселерометра BMA180

Можно использовать не только акселерометры с аналоговым выходом, но и с цифровым (I2C, SPI) выходом. Акселерометр BMA180 взят в качестве примера т.к. он очень чувствительный. Акселерометр BMA180 хорошо стабилизирует колебания напряжения питания. Поэтому нет необходимости в конденсаторе. Также не нужны резисторы для формирования опорного напряжения.




Обратите внимание что акселерометр BMA180 питается от напряжения 3.3V.

Соединения:

Arduino Nano и акселерометр BMA180
3V3 < − − − > VDD
D3 < − − − > GND
D7 < − − − > SDO
A4 < − − − > SDI
A5 < − − − > SCK

Arduino Nano и HM-10 модуль
+5V < − − − > VCC
A0 < − − − > GND
TXD < − − − > RXD
RXD < − − − > TXD

1:

1024 / 5460 = 0.188

2:

1000

3:

Нижняя граница измерения.

Sample code
BMA180 Triple Axis Accelerometer datasheet

Скетч 6:

///////////////////////////////
// © 2017 Dmitriy Kharutskiy //
///////////////////////////////

// BMA180 triple axis accelerometer sample code //
// http://www.geeetech.com/wiki/index.php/BMA180_Triple_Axis_Accelerometer_Breakout //

#include <Wire.h> 
#define BMA180 0x40  //Address of the accelerometer
#define RESET 0x10   
#define PWR 0x0D
#define BW 0x20
#define RANGE 0x35
//#define DATA 0x02
#define DATA_X 0x02
#define DATA_Y 0x04
#define DATA_Z 0x06


//************************************************************
// General settings
//************************************************************

#define BandWidth B0111 // Page 28 of the datasheet for the BMA180

//#define AccelRange B000 // +/- 1g (Page 28)
#define AccelRange B001 // +/- 1.5g
//#define AccelRange B010 // +/- 2g
//#define AccelRange B011 // +/- 3g
//#define AccelRange B100 // +/- 4g
//#define AccelRange B101 // +/- 8g
//#define AccelRange B110 // +/- 16g

bool AxisX = true;
bool AxisY = false;
bool AxisZ = false;

int offx = 0;

//************************************************************


byte ByteArr[20];
int i = 0;
int ii = 0;
int AccelValue = 0;
int LastAccelValue = 0;
int dValue = 0;

void setup() 
{ 
	//Put your setup code here, to run once:
		
	//Opens serial port, sets data rate.
	//Serial.begin(9600); 
	Serial.begin(115200); 

	//A0 => GND
	pinMode(A0, OUTPUT); 
	digitalWrite(A0, LOW);
	//A1 => High impedance
	pinMode(A1, INPUT);
	digitalWrite(A1, LOW);
	//A2 => High impedance
	pinMode(A2, INPUT);
	digitalWrite(A2, LOW);
	//A3 => High impedance
	pinMode(A3, INPUT);
	digitalWrite(A3, LOW);

	//D3 => GND
	pinMode(3, OUTPUT); 
	digitalWrite(3, LOW);  
	//D7 => GND
	pinMode(7, OUTPUT); 
	digitalWrite(7, LOW);  

	//Initializing sensors
	Wire.begin(); 
	AccelerometerInit(); 
	
	delay(500); //Pauses the program for the amount of time (in miliseconds) specified as parameter.
} 

void loop() 
{ 
	//Put your main code here, to run repeatedly:
	
	AccelValue = AccelerometerRead();

	if (i < 3)
	{
		ByteArr[ii] = char(-128);
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue);
	}
	else
	{
		dValue = AccelValue - LastAccelValue;
		if (abs(dValue) > 127)
		{
			ByteArr[ii] = char(-128);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue);
		}
		else
		{
			ByteArr[ii] = char(dValue);
		}
	}
	LastAccelValue = AccelValue;
    
	i++;
	ii++;
	WriteFunction();

	//delayMicroseconds(500); // ~820 Hz.
	//delayMicroseconds(400); // ~890 Hz. MAX for Serial.begin(9600)
	//delayMicroseconds(200); // ~1100 Hz.
	//delayMicroseconds(100); // ~1220 Hz.
	delayMicroseconds(10); // ~1370 Hz.
}

//************************************************************
// Functions
//************************************************************

//Initializing sensors
void AccelerometerInit() 
{ 
	byte temp[1];
	byte temp1;
  
	writeTo(BMA180, RESET, 0xB6);
 
	// Wake up mode
	writeTo(BMA180, PWR, 0x10);
 
	// Band width,
	readFrom(BMA180, BW, 1, temp);
	temp1 = (temp[0] & 0x0F) | (BandWidth << 4);
	writeTo(BMA180, BW, temp1); 
    
	// Acceleration range 
	readFrom(BMA180, RANGE, 1, temp);  
	temp1 = (temp[0] & 0xF1) | (AccelRange << 1);
	writeTo(BMA180, RANGE, temp1);
}

//Writes val to address register on ACC
void writeTo(int DEVICE, byte address, byte val) 
{
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.write(address); //send register address
	Wire.write(val); //send value to write
	Wire.endTransmission(); //end transmission
}

//Reads num bytes starting from address register in to buff array
void readFrom(int DEVICE, byte address, int num, byte buff[])
{
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.write(address); //send register address
	Wire.endTransmission(); //end transmission
 
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.requestFrom(DEVICE, num); //request num byte from ACC
 
	int i = 0;
	while(Wire.available()) //ACC may abnormal
	{
		buff[i] = Wire.read(); //receive a byte
		i++;
	}
	Wire.endTransmission(); //end transmission
}

//Read in the 1 axis data, each one is 14 bits 
int AccelerometerRead() 
{ 
	int n = 2;
	byte result[2];
	byte AxisAddress = (AxisX) ? DATA_X : (AxisY) ? DATA_Y : (AxisZ) ? DATA_Z : DATA_X;
  
	readFrom(BMA180, AxisAddress, n, result);
 
	int x = ((result[0] | result[1] << 8) >> 2) + offx;

	return x + 8192;
}

void WriteFunction()
{
	if (ii == 20) 
	{
		Serial.write(ByteArr, ii);
		ii = 0;
	}
  
	if (i >= 200)
	{
		i = 0;
	}
}


Скетч 7 (XY):

///////////////////////////////
// © 2017 Dmitriy Kharutskiy //
///////////////////////////////

// BMA180 triple axis accelerometer sample code //
// http://www.geeetech.com/wiki/index.php/BMA180_Triple_Axis_Accelerometer_Breakout //

#include <Wire.h> 
#define BMA180 0x40  //Address of the accelerometer
#define RESET 0x10   
#define PWR 0x0D
#define BW 0x20
#define RANGE 0x35
//#define DATA 0x02
#define DATA_X 0x02
#define DATA_Y 0x04
#define DATA_Z 0x06


//************************************************************
// General settings
//************************************************************

#define BandWidth B0111 // Page 28 of the datasheet for the BMA180

//#define AccelRange B000 // +/- 1g (Page 28)
#define AccelRange B001 // +/- 1.5g
//#define AccelRange B010 // +/- 2g
//#define AccelRange B011 // +/- 3g
//#define AccelRange B100 // +/- 4g
//#define AccelRange B101 // +/- 8g
//#define AccelRange B110 // +/- 16g

bool AxisX = true;
bool AxisY = true;
bool AxisZ = false;

int offx = 0;  
int offy = 0;  
int offz = 0;  

//************************************************************


byte ByteArr[20];
int i = 0;
int ii = 0;
int AccelValue1 = 0;
int AccelValue2 = 0;
int LastAccelValue1 = 0;
int LastAccelValue2 = 0;
int dValue1 = 0;
int dValue2 = 0;

void setup() 
{ 
	//Put your setup code here, to run once:
		
	//Opens serial port, sets data rate.
	//Serial.begin(9600); 
	Serial.begin(115200); 

	//A0 => GND
	pinMode(A0, OUTPUT); 
	digitalWrite(A0, LOW);
	//A1 => High impedance
	pinMode(A1, INPUT);
	digitalWrite(A1, LOW);
	//A2 => High impedance
	pinMode(A2, INPUT);
	digitalWrite(A2, LOW);
	//A3 => High impedance
	pinMode(A3, INPUT);
	digitalWrite(A3, LOW);

	//D3 => GND
	pinMode(3, OUTPUT); 
	digitalWrite(3, LOW);  
	//D7 => GND
	pinMode(7, OUTPUT); 
	digitalWrite(7, LOW);  

	//Initializing sensors
	Wire.begin(); 
	AccelerometerInit(); 
	
	delay(500); //Pauses the program for the amount of time (in miliseconds) specified as parameter.
} 

void loop() 
{ 
	//Put your main code here, to run repeatedly:
	
	AccelerometerRead();

	if (i < 5)
	{
		ByteArr[ii] = char(-128);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue1);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue1);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue2);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue2);
	}
	else
	{
		dValue1 = AccelValue1 - LastAccelValue1;
		dValue2 = AccelValue2 - LastAccelValue2;
		
		if (abs(dValue1) > 127 || abs(dValue2) > 127)
		{
			ByteArr[ii] = char(-128);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue2);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue2);
		}
		else
		{
			ByteArr[ii] = char(dValue1);			
			i++;
			ii++;
			WriteFunction();
			
			ByteArr[ii] = char(dValue2);			
		}
	}
	LastAccelValue1 = AccelValue1;
	LastAccelValue2 = AccelValue2;
    
	i++;
	ii++;
	WriteFunction();

	//delayMicroseconds(1000); //~465 Hz. MAX for Serial.begin(9600).
	delayMicroseconds(1); //Serial.begin(115200), ~890 Hz. MAX.
}

//************************************************************
// Functions
//************************************************************

//Initializing sensors
void AccelerometerInit() 
{ 
	byte temp[1];
	byte temp1;
  
	writeTo(BMA180, RESET, 0xB6);
 
	// Wake up mode
	writeTo(BMA180, PWR, 0x10);
 
	// Band width,
	readFrom(BMA180, BW, 1, temp);
	temp1 = (temp[0] & 0x0F) | (BandWidth << 4);
	writeTo(BMA180, BW, temp1); 
    
	// Acceleration range 
	readFrom(BMA180, RANGE, 1, temp);  
	temp1 = (temp[0] & 0xF1) | (AccelRange << 1);
	writeTo(BMA180, RANGE, temp1);
}

//Writes val to address register on ACC
void writeTo(int DEVICE, byte address, byte val) 
{
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.write(address); //send register address
	Wire.write(val); //send value to write
	Wire.endTransmission(); //end transmission
}

//Reads num bytes starting from address register in to buff array
void readFrom(int DEVICE, byte address, int num, byte buff[])
{
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.write(address); //send register address
	Wire.endTransmission(); //end transmission
 
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.requestFrom(DEVICE, num); //request num byte from ACC
 
	int i = 0;
	while(Wire.available()) //ACC may abnormal
	{
		buff[i] = Wire.read(); //receive a byte
		i++;
	}
	Wire.endTransmission(); //end transmission
}

//Read in the 3 axis data, each one is 14 bits 
void AccelerometerRead() 
{ 
	int n = 6;
	byte result[6];
  
	readFrom(BMA180, DATA_X, n, result); 
 
	int x = ((result[0] | result[1] << 8) >> 2) + offx;
	x = x + 8192;

	int y = ((result[2] | result[3] << 8) >> 2) + offy;
	y = y + 8192; 

	int z = ((result[4] | result[5] << 8) >> 2) + offz;
	z = z + 8192; 

  AccelValue1 = (AxisX) ? x : (AxisY && AxisZ) ? y : x;
  AccelValue2 = (AxisY && AxisX) ? y : (AxisZ) ? z : y;
}

void WriteFunction()
{
	if (ii == 20) 
	{
		Serial.write(ByteArr, ii);
		ii = 0;
	}
  
	if (i >= 400)
	{
		i = 0;
	}
}


Скетч 8 (XYZ):

///////////////////////////////
// © 2017 Dmitriy Kharutskiy //
///////////////////////////////

// BMA180 triple axis accelerometer sample code //
// http://www.geeetech.com/wiki/index.php/BMA180_Triple_Axis_Accelerometer_Breakout //

#include <Wire.h> 
#define BMA180 0x40  //Address of the accelerometer
#define RESET 0x10   
#define PWR 0x0D
#define BW 0x20
#define RANGE 0x35
//#define DATA 0x02
#define DATA_X 0x02
#define DATA_Y 0x04
#define DATA_Z 0x06


//************************************************************
// General settings
//************************************************************

#define BandWidth B0111 // Page 28 of the datasheet for the BMA180

//#define AccelRange B000 // +/- 1g (Page 28)
#define AccelRange B001 // +/- 1.5g
//#define AccelRange B010 // +/- 2g
//#define AccelRange B011 // +/- 3g
//#define AccelRange B100 // +/- 4g
//#define AccelRange B101 // +/- 8g
//#define AccelRange B110 // +/- 16g

int offx = 0;  
int offy = 0;  
int offz = 0;  

//************************************************************


byte ByteArr[20];
int i = 0;
int ii = 0;
int AccelValue1 = 0;
int AccelValue2 = 0;
int AccelValue3 = 0;
int LastAccelValue1 = 0;
int LastAccelValue2 = 0;
int LastAccelValue3 = 0;
int dValue1 = 0;
int dValue2 = 0;
int dValue3 = 0;

void setup() 
{ 
	//Put your setup code here, to run once:
		
	//Opens serial port, sets data rate.
	//Serial.begin(9600); 
	Serial.begin(115200); 

	//A0 => GND
	pinMode(A0, OUTPUT); 
	digitalWrite(A0, LOW);
	//A1 => High impedance
	pinMode(A1, INPUT);
	digitalWrite(A1, LOW);
	//A2 => High impedance
	pinMode(A2, INPUT);
	digitalWrite(A2, LOW);
	//A3 => High impedance
	pinMode(A3, INPUT);
	digitalWrite(A3, LOW);

	//D3 => GND
	pinMode(3, OUTPUT); 
	digitalWrite(3, LOW);  
	//D7 => GND
	pinMode(7, OUTPUT); 
	digitalWrite(7, LOW);  

	//Initializing sensors
	Wire.begin(); 
	AccelerometerInit(); 
	
	delay(500); //Pauses the program for the amount of time (in miliseconds) specified as parameter.
} 

void loop() 
{ 
	//Put your main code here, to run repeatedly:
	
	AccelerometerRead();

	if (i < 7)
	{
		ByteArr[ii] = char(-128);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue1);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue1);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue2);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue2);
		
		i++;
		ii++;
		ByteArr[ii] = highByte(AccelValue3);
		i++;
		ii++;    
		ByteArr[ii] = lowByte(AccelValue3);
	}
	else
	{
		dValue1 = AccelValue1 - LastAccelValue1;
		dValue2 = AccelValue2 - LastAccelValue2;
		dValue3 = AccelValue3 - LastAccelValue3;
		
		if (abs(dValue1) > 127 || abs(dValue2) > 127 || abs(dValue3) > 127)
		{
			ByteArr[ii] = char(-128);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue1);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue2);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue2);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = highByte(AccelValue3);
			i++;
			ii++;
			WriteFunction();
      
			ByteArr[ii] = lowByte(AccelValue3);
		}
		else
		{
			ByteArr[ii] = char(dValue1);			
			i++;
			ii++;
			WriteFunction();
			
			ByteArr[ii] = char(dValue2);			
			i++;
			ii++;
			WriteFunction();
			
			ByteArr[ii] = char(dValue3);
		}
	}
	LastAccelValue1 = AccelValue1;
	LastAccelValue2 = AccelValue2;
	LastAccelValue3 = AccelValue3;
    
	i++;
	ii++;
	WriteFunction();

	//delay(2); //~310 Hz. MAX for Serial.begin(9600).
	delayMicroseconds(650); //Serial.begin(115200), ~550 Hz. MAX.
}

//************************************************************
// Functions
//************************************************************

//Initializing sensors
void AccelerometerInit() 
{ 
	byte temp[1];
	byte temp1;
  
	writeTo(BMA180, RESET, 0xB6);
 
	// Wake up mode
	writeTo(BMA180, PWR, 0x10);
 
	// Band width,
	readFrom(BMA180, BW, 1, temp);
	temp1 = (temp[0] & 0x0F) | (BandWidth << 4);
	writeTo(BMA180, BW, temp1); 
    
	// Acceleration range 
	readFrom(BMA180, RANGE, 1, temp);  
	temp1 = (temp[0] & 0xF1) | (AccelRange << 1);
	writeTo(BMA180, RANGE, temp1);
}

//Writes val to address register on ACC
void writeTo(int DEVICE, byte address, byte val) 
{
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.write(address); //send register address
	Wire.write(val); //send value to write
	Wire.endTransmission(); //end transmission
}

//Reads num bytes starting from address register in to buff array
void readFrom(int DEVICE, byte address, int num, byte buff[])
{
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.write(address); //send register address
	Wire.endTransmission(); //end transmission
 
	Wire.beginTransmission(DEVICE); //start transmission to ACC
	Wire.requestFrom(DEVICE, num); //request num byte from ACC
 
	int i = 0;
	while(Wire.available()) //ACC may abnormal
	{
		buff[i] = Wire.read(); //receive a byte
		i++;
	}
	Wire.endTransmission(); //end transmission
}

//Read in the 3 axis data, each one is 14 bits 
void AccelerometerRead() 
{ 
	int n = 6;
	byte result[6];
  
	readFrom(BMA180, DATA_X, n, result); 
 
	int x = ((result[0] | result[1] << 8) >> 2) + offx;
	AccelValue1 = x + 8192;

	int y = ((result[2] | result[3] << 8) >> 2) + offy;
	AccelValue2 = y + 8192; 

	int z = ((result[4] | result[5] << 8) >> 2) + offz;
	AccelValue3 = z + 8192; 
}

void WriteFunction()
{
	if (ii == 20) 
	{
		Serial.write(ByteArr, ii);
		ii = 0;
	}
  
	if (i >= 600)
	{
		i = 0;
	}
}



Bluetooth акселерометр на основе Arduino Nano 33 BLE



Arduino Nano 33 BLE
Getting started with the Arduino NANO 33 BLE
LSM9DS1 datasheet
The NANO 33 BLE has TWO COM ports
New to the NANO 33 BLE, SENSE, IOT please read this first
NINA-B3 datasheet
ArduinoBLE library
Installing Additional Arduino Libraries
Nano 33 BLE vs Nano Every speed
Handling loss of connection
BLE nano 33 does not report or disconnect from centra

Используйте ТОЛЬКО старую библиотеку ArduinoBLE (ArduinoBLE ver. 1.1.2) и старое ядро для Arduino Nano 33 BLE (Arduino Mbed OS Boards ver. 1.1.3), смотрите скриншоты ниже. При использовании новой библиотеки (ArduinoBLE ver. 1.1.3) и нового ядра (Arduino Mbed OS Boards ver. 1.1.6) получаются не верные данные (частота дискретизации постоянно меняется и обсолютно не правильная). Старые версии библиотеки и ядра можно выбрать в настройках (Installing Additional Arduino Libraries, Installing additional cores). Не устанавливайте компоненты для Arduino Nano 33 BLE автоматически предлагаемые Arduino IDE. Для проверки стабильности частоты дискретизации можно измерить частоту вибрации вращающегося внешнего жесткого диска. Пик частоты вибрации не должен менять частоту в течении нескольких минут.


Tools > Manager Libraries...


Tools > Board > Boards Manager...

Arduino Nano 33 BLE можно купить не оплачивая международную доставку, стоимость которой превышает цену Arduino Nano 33 BLE. Смотрите здесь: https://efind.ru/offer/ABX00030. Также Arduino Nano 33 BLE бывает в Амперке (amperka.ru).

Arduino Nano 33 BLE сильно отличается от Arduino Nano, например:

• К пинам (в частности к пину “+5V”) нельзя подключать напряжение больше 3.3V.
• Чтобы COM порт стал доступен для загрузки скетча, иногда нужно два раза быстро нажать на кнопку сброс на плате.
• Другой USB разъем (micro-USB). Поэтому кабель нужен другой.

Есть отличия и между встроенным в Arduino Nano 33 BLE Bluetooth и модулем HM-10:

• Я не нашел простого способа настройки Bluetooth встроенного в Arduino Nano 33 BLE (nRF52840). В то время как модуль HM-10 можно легко настроить через AT команды.
• При превышении пропускной способности Bluetooth соединения, нет явного искажения полученных данных. Поэтому проблемы в Bluetooth соединении можно не увидеть.
• Если сравнивать Arduino Nano 33 BLE работающую в режиме Bluetooth 4.0 с модулем HM-10, то модуль HM-10 намного лучше по скорости передачи данных и дальности (для HM-10 дальность передачи зависит от скорости, если скорость меньше то дальность больше).

Скетч адаптирован для смартфонов с Bluetooth 4.2 и Bluetooth 5.0. Это смартфоны начиная с iPhone 6S. Если iPhone поддерживает только Bluetooth 4.0, то в скетче нужно изменить размер передаваемого пакета на 20 (bufferSize = 20). Для смартфонов с Bluetooth 4.2 и Bluetooth 5.0 частота дискретизации (при измерении 3 осей) ограничена максимальной частотой дискретизации встроенного акселерометра (476 Hz, сделать 952 Hz не получилось). Для смартфонов с Bluetooth 4.0 максимальная частота дискретизации 119 Hz (при измерении 3 осей) и 238 Hz (при измерении 1 оси).

Если Arduino Nano 33 BLE используется без корпуса, то чтобы не запачкать плату пчелиным воском (которым плата приклеивается к исследуемому механизму) к плате нужно приклеить специальную клейкую ленту НЕ ОСТАВЛЯЮЩУЮ СЛЕДОВ. Самый простой вариант - это ХОРОШАЯ малярная лента. Но к сожалению к такой ленте плохо прилипает пчелиный воск и поэтому поверхность контакта должна быть большой.

Питание подключено через USB гнездо. При этом Arduino Nano 33 BLE работает при подключении напряжения от 4.1V до 5V. 5V указано в описании Arduino Nano 33 BLE, но проверялась работа при подключении 6.0V через USB в течении 7 часов и плата не сгорела.

1:

Для ±2 g, 1024/16384 = 0.0625
Для ±4 g, 1024/8192 = 0.125
Для ±8 g, 1024/4096 = 0.25
Для ±16 g, 1024/1365 = 0.75

2:

1000

3:

Для ±2 g, 2
Для ±4 g, 4
Для ±8 g, 8
Для ±16 g, 24

Скетч 9 (XYZ):

///////////////////////////////
// © 2020 Dmitriy Kharutskiy //
///////////////////////////////

// BMA180 triple axis accelerometer sample code //
// http://www.geeetech.com/wiki/index.php/BMA180_Triple_Axis_Accelerometer_Breakout //

#include <Wire.h> 
#include <ArduinoBLE.h>

#define ACCELEROMETER_ADDRESS 0x6B // Address of the accelerometer
#define ACCELEROMETER_STATUS_REG 0x17 // (Page 49 of the datasheet for the LSM9DS1, STATUS_REG)
#define DATA_X 0x28 // (Page 56, OUT_X_L_XL)
#define DATA_Y 0x2A // (Page 56, OUT_Y_L_XL)
#define DATA_Z 0x2C // (Page 56, OUT_Z_L_XL)

//************************************************************
// General settings
//************************************************************

#define ACCELEROMETER_SETTINGS_ADDRESS 0x20 // (Page 51 of the datasheet for the LSM9DS1, CTRL_REG6_XL)
//#define ACCELEROMETER_SETTINGS B10100000 // B[101]00000 - 476 Hz, B101[00]000 - 2 G (Page 51-52 of the datasheet for the LSM9DS1, CTRL_REG6_XL)
//#define ACCELEROMETER_SETTINGS B10110000 // B[101]10000 - 476 Hz, B101[10]000 - 4 G
//#define ACCELEROMETER_SETTINGS B10111000 // B[101]11000 - 476 Hz, B101[11]000 - 8 G
#define ACCELEROMETER_SETTINGS B10101000 // B[101]01000 - 476 Hz, B101[01]000 - 16 G
//#define ACCELEROMETER_SETTINGS B10011000 // B[100]11000 - 238 Hz, B100[11]000 - 8 G
//#define ACCELEROMETER_SETTINGS B01111000 // B[011]11000 - 119 Hz, B011[11]000 - 8 G
//#define ACCELEROMETER_SETTINGS B11011000 // B[110]11000 - 952 Hz, B110[11]000 - 8 G // DOES NOT WORK. The test shows 476 Hz instead of 952 Hz.

#define ACCELEROMETER_RESET_ADDRESS 0x22 // (Page 53, CTRL_REG8)
#define ACCELEROMETER_RESET B00000101 // (Page 53, CTRL_REG8)

int16_t offx = 0;
int16_t offy = 0;
int16_t offz = 0;

const int bufferSize = 244; // For Bluetooth 4.2 and Bluetooth 5.0 https://punchthrough.com/maximizing-ble-throughput-part-3-data-length-extension-dle-2/
//const int bufferSize = 20; // For Bluetooth 4.0 https://punchthrough.com/maximizing-ble-throughput-part-3-data-length-extension-dle-2/
BLEService accelerometerService("FFE0");
BLECharacteristic accelerometerDataChar("FFE1", BLERead | BLENotify, bufferSize, true);

int dataLengthAfterMarker = bufferSize * 3;

//************************************************************


byte ByteArr[bufferSize];
int i = 0;
int ii = 0;
int16_t AccelValue1 = 0;
int16_t AccelValue2 = 0;
int16_t AccelValue3 = 0;
int16_t LastAccelValue1 = 0;
int16_t LastAccelValue2 = 0;
int16_t LastAccelValue3 = 0;
uint16_t unsignedAccelValue = 0;
int16_t dValue1 = 0;
int16_t dValue2 = 0;
int16_t dValue3 = 0;
long previousMicros = 0;


void setup() 
{
	// put your setup code here, to run once:

	Serial.begin(9600);

	pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected

  
	Wire1.begin(); 
	delay(50);

 
	// Initializing sensors
	initAccelerometer(); 

	initBLE();

  
	delay(500); // Pauses the program for the amount of time (in miliseconds) specified as parameter.
}

void loop() 
{
	// put your main code here, to run repeatedly:


	// wait for a BLE central
	BLEDevice central = BLE.central();
  
  
	// if a central is connected to the peripheral:
	if (central)
	{
		// turn on the LED to indicate the connection:
		digitalWrite(LED_BUILTIN, HIGH);


		// while the central is connected:
		while (central.connected()) 
		{	
			if (newDataAvailability())
			{ 
				/*
				// Sample rate testing
				long currentMicros = micros();
  				Serial.println(currentMicros - previousMicros);
  				previousMicros = micros();
  				*/

				readAccelerometer();
				//Serial.println(AccelValue1);  
 
				if (i < 3)
				{					
					ByteArr[ii] = char(-128);    
					i++;
					ii++;
					
					unsignedAccelValue = AccelValue1 + 32768;
					ByteArr[ii] = highByte(unsignedAccelValue);
					i++;
					ii++;    
					ByteArr[ii] = lowByte(unsignedAccelValue);
    
					i++;
					ii++;
					unsignedAccelValue = AccelValue2 + 32768;
					ByteArr[ii] = highByte(unsignedAccelValue);
					i++;
					ii++;    
					ByteArr[ii] = lowByte(unsignedAccelValue);
    
					i++;
					ii++;
					unsignedAccelValue = AccelValue3 + 32768;
					ByteArr[ii] = highByte(unsignedAccelValue);
					i++;
					ii++;    
					ByteArr[ii] = lowByte(unsignedAccelValue);
				}
				else
				{
					dValue1 = AccelValue1 - LastAccelValue1;
					dValue2 = AccelValue2 - LastAccelValue2;
					dValue3 = AccelValue3 - LastAccelValue3;
    
					if (abs(dValue1) > 127 || abs(dValue2) > 127 || abs(dValue3) > 127)
					{
						ByteArr[ii] = char(-128);
						i = 0;						
						i++;
						ii++;
						sendBuffer();
      
						unsignedAccelValue = AccelValue1 + 32768;
						ByteArr[ii] = highByte(unsignedAccelValue);
						i++;
						ii++;
						sendBuffer();
						  
						ByteArr[ii] = lowByte(unsignedAccelValue);
						i++;
						ii++;
						sendBuffer();
      
						unsignedAccelValue = AccelValue2 + 32768;
						ByteArr[ii] = highByte(unsignedAccelValue);
						i++;
						ii++;
						sendBuffer();
      
						ByteArr[ii] = lowByte(unsignedAccelValue);
						i++;
						ii++;
						sendBuffer();
      
						unsignedAccelValue = AccelValue3 + 32768;
						ByteArr[ii] = highByte(unsignedAccelValue);
						i++;
						ii++;
						sendBuffer();
      
						ByteArr[ii] = lowByte(unsignedAccelValue);
					}
					else
					{
						ByteArr[ii] = char(dValue1);      
						i++;
						ii++;
						sendBuffer();
      
						ByteArr[ii] = char(dValue2);      
						i++;
						ii++;
						sendBuffer();
      
						ByteArr[ii] = char(dValue3);
					}
				}
				LastAccelValue1 = AccelValue1;
				LastAccelValue2 = AccelValue2;
				LastAccelValue3 = AccelValue3;
    
				i++;
				ii++;
				sendBuffer();
			}
		}
		
		// when the central disconnects, turn off the LED:
		digitalWrite(LED_BUILTIN, LOW);
	}
}

//************************************************************
// Functions
//************************************************************

// Initializing sensors
void initAccelerometer() 
{ 
	byte temp[1];
	byte temp1;

	// RESET
	writeTo(ACCELEROMETER_ADDRESS, ACCELEROMETER_RESET_ADDRESS, 0x05);

	// ACCELEROMETER SETTING: acceleration range, band width
	writeTo(ACCELEROMETER_ADDRESS, ACCELEROMETER_SETTINGS_ADDRESS, ACCELEROMETER_SETTINGS);

	delay(100);
}

// Initializing BLE
void initBLE() 
{ 
	// begin initialization
	if (!BLE.begin()) 
	{		
		while (1)
		{
			Serial.println("starting BLE failed!");
			delay(1000);
		}
	}

	BLE.setLocalName("Vibration_Analysis_App");
	BLE.setAdvertisedService(accelerometerService); // add the service UUID
	accelerometerService.addCharacteristic(accelerometerDataChar); // add the battery level characteristic
	BLE.addService(accelerometerService); // Add the battery service

	// start advertising
	BLE.advertise();
}


// Writes val to address register on ACC
void writeTo(int DEVICE, byte address, byte val) 
{
	Wire1.beginTransmission(DEVICE); // start transmission to ACC
	Wire1.write(address); // send register address
	Wire1.write(val); // send value to write
	Wire1.endTransmission(); // end transmission
}

// Reads num bytes starting from address register in to buff array
void readFrom(int DEVICE, byte address, int num, byte buff[])
{
	Wire1.beginTransmission(DEVICE); // start transmission to ACC
	Wire1.write(address); // send register address
	Wire1.endTransmission(); // end transmission
 
	Wire1.beginTransmission(DEVICE); // start transmission to ACC
	Wire1.requestFrom(DEVICE, num); // request num byte from ACC
 
	int n = 0;
	while(Wire1.available()) // ACC may abnormal
	{
		buff[n] = Wire1.read(); // receive a byte
		n++;
	}
	Wire1.endTransmission(); // end transmission
}

// Read in the 3 axis data, each one is 16 bits 
void readAccelerometer() 
{ 
	int n = 6;
	byte result[6];
 
	readFrom(ACCELEROMETER_ADDRESS, DATA_X, n, result);
 
	AccelValue1 = int16_t(result[1] << 8 | result[0]) + offx;
	AccelValue2 = int16_t(result[3] << 8 | result[2]) + offy;
	AccelValue3 = int16_t(result[5] << 8 | result[4]) + offz;
}

void sendBuffer()
{
	if (ii == bufferSize) 
	{		
		long beforeMicros = micros();
		
		accelerometerDataChar.writeValue(ByteArr, ii);	
		
		long afterMicros = micros();		
		//Serial.println(afterMicros - beforeMicros); // Testing delay when sending data
				
		ii = 0;
		
		if (i >= dataLengthAfterMarker) i = 0;
	}	
}

bool newDataAvailability()
{
	byte temp[1];
	readFrom(ACCELEROMETER_ADDRESS, ACCELEROMETER_STATUS_REG, 1, temp);

	if ((temp[0] & B00000001) != 0) return true;

	return false;
} 


Скетч 10 (X):

///////////////////////////////
// © 2020 Dmitriy Kharutskiy //
///////////////////////////////

// BMA180 triple axis accelerometer sample code //
// http://www.geeetech.com/wiki/index.php/BMA180_Triple_Axis_Accelerometer_Breakout //

#include <Wire.h> 
#include <ArduinoBLE.h>

#define ACCELEROMETER_ADDRESS 0x6B // Address of the accelerometer
#define ACCELEROMETER_STATUS_REG 0x17 // (Page 49 of the datasheet for the LSM9DS1, STATUS_REG)
#define DATA_X 0x28 // (Page 56, OUT_X_L_XL)
#define DATA_Y 0x2A // (Page 56, OUT_Y_L_XL)
#define DATA_Z 0x2C // (Page 56, OUT_Z_L_XL)

//************************************************************
// General settings
//************************************************************

#define ACCELEROMETER_SETTINGS_ADDRESS 0x20 // (Page 51 of the datasheet for the LSM9DS1, CTRL_REG6_XL)
//#define ACCELEROMETER_SETTINGS B10100000 // B[101]00000 - 476 Hz, B101[00]000 - 2 G (Page 51-52 of the datasheet for the LSM9DS1, CTRL_REG6_XL)
//#define ACCELEROMETER_SETTINGS B10110000 // B[101]10000 - 476 Hz, B101[10]000 - 4 G
//#define ACCELEROMETER_SETTINGS B10111000 // B[101]11000 - 476 Hz, B101[11]000 - 8 G
#define ACCELEROMETER_SETTINGS B10101000 // B[101]01000 - 476 Hz, B101[01]000 - 16 G
//#define ACCELEROMETER_SETTINGS B10011000 // B[100]11000 - 238 Hz, B100[11]000 - 8 G
//#define ACCELEROMETER_SETTINGS B01111000 // B[011]11000 - 119 Hz, B011[11]000 - 8 G
//#define ACCELEROMETER_SETTINGS B11011000 // B[110]11000 - 952 Hz, B110[11]000 - 8 G // DOES NOT WORK. The test shows 476 Hz instead of 952 Hz.

#define ACCELEROMETER_RESET_ADDRESS 0x22 // (Page 53, CTRL_REG8)
#define ACCELEROMETER_RESET B00000101 // (Page 53, CTRL_REG8)

bool AxisX = true;
bool AxisY = false;
bool AxisZ = false;

int16_t offx = 0;

const int bufferSize = 244; // For Bluetooth 4.2 and Bluetooth 5.0 https://punchthrough.com/maximizing-ble-throughput-part-3-data-length-extension-dle-2/
//const int bufferSize = 20; // For Bluetooth 4.0 https://punchthrough.com/maximizing-ble-throughput-part-3-data-length-extension-dle-2/
BLEService accelerometerService("FFE0");
BLECharacteristic accelerometerDataChar("FFE1", BLERead | BLENotify, bufferSize, true);

int dataLengthAfterMarker = bufferSize * 3;

//************************************************************


byte ByteArr[bufferSize];
int i = 0;
int ii = 0;
int16_t AccelValue = 0;
int16_t LastAccelValue = 0;
uint16_t unsignedAccelValue = 0;
int16_t dValue = 0;
long previousMicros = 0;


void setup() 
{
	// put your setup code here, to run once:

	Serial.begin(9600);

	pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected

  
	Wire1.begin(); 
	delay(50);

 
	// Initializing sensors
	initAccelerometer(); 

	initBLE();

  
	delay(500); // Pauses the program for the amount of time (in miliseconds) specified as parameter.
}

void loop() 
{
	// put your main code here, to run repeatedly:


	// wait for a BLE central
	BLEDevice central = BLE.central();

	// if a central is connected to the peripheral:
	if (central) 
	{
		// turn on the LED to indicate the connection:
		digitalWrite(LED_BUILTIN, HIGH);


		// while the central is connected:
		while (central.connected()) 
		{  
			if (newDataAvailability()) 
			{ 
				/*
				// Sample rate testing
				long currentMicros = micros();
				Serial.println(currentMicros - previousMicros);
				previousMicros = micros();
				*/
  
				AccelValue = readAccelerometer();
				//Serial.println(AccelValue);
 
				if (i == 0)
				{
					ByteArr[ii] = char(-128);
					i++;
					ii++;
    
					unsignedAccelValue = AccelValue + 32768;
					ByteArr[ii] = highByte(unsignedAccelValue);
					i++;
					ii++;    
					ByteArr[ii] = lowByte(unsignedAccelValue);
				}
				else
				{
					dValue = AccelValue - LastAccelValue;
					
					if (abs(dValue) > 127)
					{
						ByteArr[ii] = char(-128);
						i = 0;      
						i++;
						ii++;
						sendBuffer();

						unsignedAccelValue = AccelValue + 32768;
						ByteArr[ii] = highByte(unsignedAccelValue);
						i++;
						ii++;
						sendBuffer();
      
						ByteArr[ii] = lowByte(unsignedAccelValue);
					}
					else
					{
						ByteArr[ii] = char(dValue);
					}
				}
				LastAccelValue = AccelValue;
    
				i++;
				ii++;
				sendBuffer();
			}
		}

		// when the central disconnects, turn off the LED:
		digitalWrite(LED_BUILTIN, LOW);
	}
}

//************************************************************
// Functions
//************************************************************

// Initializing sensors
void initAccelerometer() 
{ 
	byte temp[1];
	byte temp1;

	// RESET
	writeTo(ACCELEROMETER_ADDRESS, ACCELEROMETER_RESET_ADDRESS, 0x05);

	// ACCELEROMETER SETTING: acceleration range, band width
	writeTo(ACCELEROMETER_ADDRESS, ACCELEROMETER_SETTINGS_ADDRESS, ACCELEROMETER_SETTINGS);

	delay(100);
}

// Initializing BLE
void initBLE() 
{ 
	// begin initialization
	if (!BLE.begin()) 
	{
		while (1)
		{
			Serial.println("starting BLE failed!");
			delay(1000);
		}
	}

	BLE.setLocalName("Vibration_Analysis_App");
	BLE.setAdvertisedService(accelerometerService); // add the service UUID
	accelerometerService.addCharacteristic(accelerometerDataChar); // add the battery level characteristic
	BLE.addService(accelerometerService); // Add the battery service

	// start advertising
	BLE.advertise();
}

// Writes val to address register on ACC
void writeTo(int DEVICE, byte address, byte val) 
{
	Wire1.beginTransmission(DEVICE); // start transmission to ACC
	Wire1.write(address); // send register address
	Wire1.write(val); // send value to write
	Wire1.endTransmission(); // end transmission
}

// Reads num bytes starting from address register in to buff array
void readFrom(int DEVICE, byte address, int num, byte buff[])
{
	Wire1.beginTransmission(DEVICE); // start transmission to ACC
	Wire1.write(address); // send register address
	Wire1.endTransmission(); // end transmission
 
	Wire1.beginTransmission(DEVICE); // start transmission to ACC
	Wire1.requestFrom(DEVICE, num); // request num byte from ACC
 
	int n = 0;
	while(Wire1.available()) // ACC may abnormal
	{
		buff[n] = Wire1.read(); // receive a byte
		n++;
	}
	Wire1.endTransmission(); // end transmission
}

// Read in the 1 axis data, each one is 16 bits 
int16_t readAccelerometer() 
{ 
	int n = 2;
	byte result[2];
	byte AxisAddress = (AxisX) ? DATA_X : (AxisY) ? DATA_Y : (AxisZ) ? DATA_Z : DATA_X;
  
	readFrom(ACCELEROMETER_ADDRESS, AxisAddress, n, result);
 
	int16_t x = int16_t(result[1] << 8 | result[0]) + offx;

	return x;
}

void sendBuffer()
{
	if (ii == bufferSize) 
	{		
		long beforeMicros = micros();
   
		accelerometerDataChar.writeValue(ByteArr, ii);		
		
		long afterMicros = micros();
		//Serial.println(afterMicros - beforeMicros); // Testing delay when sending data

		ii = 0;

		if (i >= dataLengthAfterMarker) i = 0;
	}
}

bool newDataAvailability()
{
	byte temp[1];
	readFrom(ACCELEROMETER_ADDRESS, ACCELEROMETER_STATUS_REG, 1, temp);

	if ((temp[0] & B00000001) != 0) return true;

	return false;
}



Шоппинг





1:


eBay: "bluetooth module hm-10"

2:


eBay: "capacitor electrolytic 220uF"

3:


AliExpress: "breadboard jumper wires 65 pcs"


AliExpress: "jump wire female to female 20cm"


eBay: "breadboard U shape jumper"

4:


eBay: "Arduino Nano"
(Для Mac eBay: "Arduino Nano FT232RL")

5:


eBay: "resistor 1W kit"

6:


AliExpress: "breadboard 170"

7:


eBay: "battery box 3AA switch"

8:


AliExpress: "ADXL335"

И (ЕСЛИ НУЖНО)


eBay: "2.54 mm 1x40 male angle connector"

9:


AliExpress: "phototransistor 3DU5C"

10:


AliExpress: "laser module red"

11:


eBay: "AD623AN"

12:


eBay: "10K 3296W"

13:


eBay: "BMA180"

14:


eBay: "AA battery box USB"