Система автоматического тестирования ВМГ (народный проект)
думаю над созданием чего-то подобного но за основу решил взять такую платку чтоб еще паралельно на дисплее видеть снимаемые параметры.
www.aliexpress.com/item/…/759195015.html
ссылочку тут размещу… за 18 баксов можно получить 5 датчиков на различный вес от 1 до 7кг
Сырой, но уже работоспособный скетч проекта.
Полностью готово меню режимов тестирования.
Имеется три режима тестирования:
первый - автомат с шагом 50, 65, 75, 85 и 100 процентов (как в магазинных тестах), показания снимаются автоматически
второй - то же автомат, с шагом в один от 0 до 100 процентов, показания снимаются автоматически
третий - ручной, вы можете сами набрать процент от 0 до 100 или с помощью +/- подкорректировать требуемый процент, показания снимаются путем нажатии клавиши “r”
Во всех режимах предусмотрена защита от моментального набора оборотов, то есть набор оборотов в большую сторону будет происходить плавно (плавный набор оборотов), так же предусмотрено прерывание теста при нажатии на любую не задействованную клавишу.
Следующая задача, организовать меню и работу калибровок (пока калибровать можно только через изменение скетча).
#include <Servo.h> // добавляем библиотеку для работы с сервоприводами
//объявление переменных
//подключаемые разьемы на ардуине
#define servoPin 3 // для дальнейшей работы назовем 3 пин как servoPin
int DATA = 4; //пин D4 подключаем АЦП тяги
int SCLK = 5; //пин D5 подключаем АЦП тяги
int PWDN = 6; //пин D6 подключаем АЦП тяги
#define CurrPin A0 //пин A0 датчик тока
#define VoltPin A1 //пин A1 датчик напряжения
#define servoMinImp 544 // 544 это стандартная длина импульса при котором сервопривод должен принять положение 0°
#define servoMaxImp 2400 // 2400 это эталонная длина импульса при котором сервопривод должен принять положение 180°
//переменные для работы
float CurrentValue = 0; //переменная для расчета тока (с плавающей точкой)
float CurrentValueRes = 0; //переменная с результатом для расчета тока (с плавающей точкой)
float VoltageValue = 0; //переменная для расчета напряжения (с плавающей точкой)
int32_t Weight = 0; //переменная для расчета тяги (32 разряда)
//переменные для нулевых значений
int32_t WeightNull = 0; //нулевое значение по весу (переменная калибруется при включении)
int CountNull = 0; //нулевое значение по току, данная переменная для однонаправленных датчиков ACS758 (с буквой U) не используется (переменная калибруется при включении)
//эти переменные заполняются пользователем
int ISensor = 200; //максимальное значение измеряемое датчиком (смотрим даташит по ним)
Servo myServo;
int val; //здесь будет храниться принятый символ
int n;
int error = 0;
int throttle = 0;
String strnumber = "0";
int throttleOld = 0;
//инициализация
void setup() {
//инициализация I/O
pinMode(DATA, INPUT);
pinMode(SCLK, OUTPUT);
pinMode(PWDN, OUTPUT);
digitalWrite(PWDN, HIGH);
//скорость порта
Serial.begin(9600);
//читаем нулевые значения по весу и току
WeightNull = getSensorValueWeight();
CountNull = analogRead(CurrPin);
myServo.attach(servoPin, servoMinImp, servoMaxImp);
// устанавливаем пин как вывод управления сервоприводом,
// а также для работы сервопривода непосредственно в диапазоне углов от 0 до 180° задаем мин и макс значения импульсов.
// импульсы с большей или меньшей длиной восприниматься не будут.
// для сервоприводов даже одной партии значения длин импульсов могут отличаться, может быть даже и 584-2440.
// поэкспериментируйте и найдите идеальные длины импульсов конкретно для вашего сервопривода.
myServo.writeMicroseconds(set_pos(0));
}
//чтение вводимой строки из терминала
String readText(int n){
int i = 0;
String str;
while (i<n) {
while (!(Serial.available()));
val = Serial.read();
if (val==13){return str;}
Serial.print(char(val));
str += char(val);
i++;
}
return str;
}
// Функция устанавливает стик газа
int set_pos(int pos) {
int tmp=(servoMaxImp - servoMinImp) /100;
pos = servoMinImp + tmp * pos;
return pos;
}
void beginTest(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - begin auto test 50, 65, 75, 85, 100%");
Serial.println("2 - begin auto test 1-100%");
Serial.println("3 - begin manual test");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){test(1);}
if (val==50){test(2);}
if (val==51){test(3);}
//if (val<=48 || val>=52){breakTest();}
Serial.println("\n\r stop test return to console");
return;
}
int test(int n){
Serial.println("\n\r============= Select action: =============");
Serial.println("8 - begin test");
Serial.println("any key - stop test and return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==56){
Serial.println("\n\r start test");
Serial.println();
if (n==1){
if (delayM(200)==1){return 0;}
("throttle from 0 to 49%"); for (n=0; n<50; n++){myServo.writeMicroseconds(set_pos(n)); if (delayM(30)==1){return 0;};}
setthrottle(50, 1); if (delayM(1000)==1){return 0;} printRez(50);
setthrottle(65, 1); if (delayM(1000)==1){return 0;} printRez(65);
setthrottle(75, 1); if (delayM(1000)==1){return 0;} printRez(75);
setthrottle(85, 1); if (delayM(1000)==1){return 0;} printRez(85);
setthrottle(100, 1); if (delayM(1000)==1){return 0;} printRez(100);
setthrottle(0, 0);
}
if (n==2){
if (delayM(200)==1){return 0;}
Serial.println("throttle from 0 to 100%"); for (n=0; n<100; n++){myServo.writeMicroseconds(set_pos(n)); printRez(n); if (delayM(50)==1){return 0;};}
Serial.println("throttle = 0%"); myServo.writeMicroseconds(set_pos(0));
}
if (n==3){
if (delayM(200)==1){return 0;}
Serial.println("select throttle percent or press +/- or r for print result");
error=0;
while (1){
while (!(Serial.available()));
val = Serial.read();
if (val==61 || val==43){if (error==1){breakTest(); return 0;}else if (throttle<=99){throttle++; setthrottle(throttle, 0);}else{Serial.println("maximal throttle 100%");}}
else if (val==45){if (error==1){breakTest(); return 0;}else if (throttle>=1){throttle--; setthrottle(throttle, 0);}else{Serial.println("minimal throttle 0%");}}
else if (val==13){Serial.println(); error=0; throttle=strnumber.toInt(); if (throttle>=101){breakTest(); return 0;} setthrottle(throttle, 1); strnumber="0";}
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
else if (val==114){printRez(throttle);}
else {breakTest(); return 0;}
}
}
}
return 0;
}
void setthrottle(int throttle, int x){
int r = 0;
if (x==0){
myServo.writeMicroseconds(set_pos(throttle));
}else if (throttleOld>=throttle){myServo.writeMicroseconds(set_pos(throttle));
}else{
r = throttle - throttleOld;
for (n=0; n<r; n++){
myServo.writeMicroseconds(set_pos(throttleOld+n));
if (delayM(30)==1){return;}
}
}
Serial.print("throttle = ");
Serial.print(throttle);
Serial.println("%");
throttleOld=throttle;
return;
}
void breakTest(){
Serial.println("throttle = 0%");
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r break");
throttle=0; strnumber="0"; throttleOld=0;
return;
}
int delayM(int m){
int k;
for (k=0; k<m; k++){
if (!(Serial.available())){}else{k = 1; breakTest(); return k;}
delay(1);
}
k = 0;
return k;
}
void servaC(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - 100%");
Serial.println("0 - 0%");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (1){
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){
myServo.writeMicroseconds(set_pos(100));
myServo.attach(servoPin, servoMinImp, servoMaxImp);
Serial.println("\n\r 100% ok");
}
if (val==48){
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r 0% ok");
}
if (val==49 || val==48){}else{return;}
}
}
void beginCalibrate(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - calibration weight");
Serial.println("2 - calibration voltage");
Serial.println("3 - calibration curent");
Serial.println("4 - calibration ESC");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){Serial.println("\n\r 1 ok");}
if (val==50){Serial.println("\n\r 2 ok");}
if (val==51){Serial.println("\n\r 3 ok");}
if (val==52){servaC();}
Serial.println("\n\r stop calibration return to console");
return;
}
//чтение данных тяги
int32_t getSensorValueWeight() {
digitalWrite(SCLK, LOW); // wake up ADC
while (digitalRead(DATA) == HIGH); // wait for data ready, stay in while-loop until LOW
Weight = shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
digitalWrite(SCLK, HIGH); // enter sleep mode
Weight = ((signed long) (Weight << 8)) >> 8; // process as int24_t (two's compliment 24bit)
return Weight;
}
int weightRez(){
Weight = (getSensorValueWeight() - WeightNull)/204.6615;
return Weight;
}
float voltageRez(){
//расчет данных напряжения
VoltageValue = analogRead(VoltPin); // считываем значение аналогового входа (напряжение)
VoltageValue = VoltageValue*0.0298217;
return VoltageValue;
}
float currentRez(){
//расчет данных тока
CurrentValue = analogRead(CurrPin); // считываем значение аналогового входа (ток)
CurrentValueRes = (CurrentValue-CountNull)*ISensor/512; //формула расчета тока для двунаправленнх датчиков ACS758
//CurrentValueRes = CurrentValue*ISensor/1024; //формула расчета тока для однонаправленных датчиков ACS758
return CurrentValueRes;
}
void printRez(int v){
//выводим результат
Serial.print(v);
Serial.print("\t");
Serial.print(weightRez());
Serial.print("\t");
Serial.print(voltageRez());
Serial.print("\t");
Serial.println(currentRez());
Serial.flush();
}
void loop()
{
Serial.println();
("Helow my friend!");
Serial.println("Please type the comands:");
Serial.println("test, calibration, null, setup");
Serial.println();
Serial.print(">");
while (!(Serial.available()));
String myString = readText(60);
if (myString=="test"){Serial.println(); beginTest(); error = 0;}
if (myString=="setup"){Serial.println("\n\r setup ok"); error = 0;}
if (myString=="calibration"){Serial.println(); beginCalibrate(); error = 0;}
if (myString=="null"){Serial.println("\n\r null ok"); error = 0;}
if (myString==""){Serial.println(); error = 0;}
if (error==0){error=1;}else{Serial.println("\n\r incorrect command");}
}
видео пока еще в процессе загрузки
за 18 баксов можно получить 5 датчиков на различный вес от 1 до 7кг
вот что подумал …
чем брать кучу датчиков , может лучше взять один на 10 кг и регулировать чувствительность за счет рычага ??? конструкция как тут
те один конец датчика крепим к основанию , к второму концу крепим пластину с мотором … так вот чувствительность можно регулировать длиной пластины … те расстоянием от крепления датчика до оси мотора …
я о другом… о том что во первых дешевле штука, во вторых можно под несколько задач/несколько клонов стендов купить
регулировать чувствительность за счет рычага
рычаг, это плохо
проблем в тензодатчике вообще нет никаких
нет никакой разницы, дорогой датчик или дешевый, любой годится
лично я ограничил точность стенда в 1 грамм, хотя можно и до одной сотой
чтобы не было рычага нужно делать как тут www.aliexpress.com/item/…/1070639659.html
те крепить пластину с мотором нужно через прокладку мотором вниз , так чтобы ось мотора была в центре датчика … если крепить как на фото в 29 посте , что удобнее ,то датчик нужно брать с запасом … с учетом того что у нас точности с большим запасом , думаю стоит брать датчик ~ 10 кг …
вот такой у меня стенд, никаких рычагов и лишних преград, никакой амортизации и пружин, все жестко закреплено и никаких смещений, единственное свободное смещение это вверх и вниз, пятка луча практически не косается датчика в спокойном состоянии, пропеллер перевернут и дует вверх тем самым прижимая пятку луча к тензодатчику, бывает, что пропеллер тяжелее чем обычно, в начале теста делаю обнуление датчика
скетч с ремарками
#include <Servo.h> // добавляем библиотеку для работы с сервоприводами
//объявление переменных
//подключаемые разьемы на ардуине
#define servoPin 3 // для дальнейшей работы назовем 3 пин как servoPin
int DATA = 4; //пин D4 подключаем АЦП тяги
int SCLK = 5; //пин D5 подключаем АЦП тяги
int PWDN = 6; //пин D6 подключаем АЦП тяги
#define CurrPin A0 //пин A0 датчик тока
#define VoltPin A1 //пин A1 датчик напряжения
#define servoMinImp 544 // 544 это стандартная длина импульса при котором сервопривод должен принять положение 0°
#define servoMaxImp 2400 // 2400 это эталонная длина импульса при котором сервопривод должен принять положение 180°
//переменные для работы
float CurrentValue = 0; //переменная для расчета тока (с плавающей точкой)
float CurrentValueRes = 0; //переменная с результатом для расчета тока (с плавающей точкой)
float VoltageValue = 0; //переменная для расчета напряжения (с плавающей точкой)
int32_t Weight = 0; //переменная для расчета тяги (32 разряда)
int val; //здесь будет храниться принятый символ
int n; //рабочая переменная
int error = 0; //так же рабочая переменная
int throttle = 0; //переменная газа
String strnumber = "0"; //переменная для временных текствых значаний
int throttleOld = 0; //переменная для хранения временных значений газа
//переменные для нулевых значений
int32_t WeightNull = 0; //нулевое значение по весу (переменная калибруется при включении)
int CountNull = 0; //нулевое значение по току, данная переменная для однонаправленных датчиков ACS758 (с буквой U) не используется (переменная калибруется при включении)
//эти переменные заполняются пользователем
int ISensor = 200; //максимальное значение измеряемое датчиком (смотрим даташит по ним)
Servo myServo;
//инициализация
void setup() {
//инициализация I/O
pinMode(DATA, INPUT);
pinMode(SCLK, OUTPUT);
pinMode(PWDN, OUTPUT);
digitalWrite(PWDN, HIGH);
//читаем нулевые значения по весу и току (обнуляем)
WeightNull = getSensorValueWeight();
CountNull = analogRead(CurrPin);
Serial.begin(9600); //скорость порта
myServo.attach(servoPin, servoMinImp, servoMaxImp);
// устанавливаем пин как вывод управления сервоприводом,
// а также для работы сервопривода непосредственно в диапазоне углов от 0 до 180° задаем мин и макс значения импульсов.
// импульсы с большей или меньшей длиной восприниматься не будут.
// для сервоприводов даже одной партии значения длин импульсов могут отличаться, может быть даже и 584-2440.
// поэкспериментируйте и найдите идеальные длины импульсов конкретно для вашего сервопривода.
myServo.writeMicroseconds(set_pos(0)); //газ в ноль при включении
}
//чтение вводимой строки из терминала
//нахождение в цыкле пока не будет нажат ENTER или набранно определенное количество символов
//возвращает набранную строку
String readText(int n){
int i = 0; //временная целая переменная
String str; //временная строковая переменная
//собираем заданное количество символов
while (i<n) {
while (!(Serial.available())); //ждем символ
val = Serial.read(); //дождавшись, читаем его
if (val==13){return str;} //если нажат Enter, прекращаем ввод символов и передаем набранную строку
Serial.print(char(val)); //показываем нажатую клавишу на терминале
str += char(val); //формируем строку
i++; //наращиваем переменную
}
return str; //передаем набранную строку заданной длины
}
// Функция устанавливает стик газа
//диапазон желательно указывать от 0 до 100
int set_pos(int pos) {
int tmp=(servoMaxImp - servoMinImp) /100;
pos = servoMinImp + tmp * pos;
return pos;
}
//вывод меню для начала теста
//предоставление выбора типа проводимого теста
void beginTest(){
//вывод меню выбора
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - begin auto test 50, 65, 75, 85, 100%");
Serial.println("2 - begin auto test 1-100%");
Serial.println("3 - begin manual test");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//по результатам выбора начинаем тест или переходим в консоль
if (val==49){test(1);} //переход на тест с указанием номера теста 1
if (val==50){test(2);} //переход на тест с указанием номера теста 2
if (val==51){test(3);} //переход на тест с указанием номера теста 3
Serial.println("\n\r stop test return to console"); return; //возвращаем в консоль
}
//начало теста
//в зависимости от выбора, запускается тест ВМГ
int test(int n){
//ждем нажатие подтверждения начала тестов
Serial.println("\n\r============= Select action: =============");
Serial.println("8 - begin test");
Serial.println("any key - stop test and return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//если подтверждение нажато, начинаем тест, иначе выходим в консоль
if (val==56){
Serial.println("\n\r start test"); Serial.println(); //информируем о начале теста
//первый тест
if (n==1){
Serial.println("set throttle 50% 65% 75% 85% 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
setthrottle(50, 1, 0); if (delayM(1000)==1){return 0;} printRez(50); //газ плавно доводим до 50%, ждем, выводим результат
setthrottle(65, 1, 0); if (delayM(1000)==1){return 0;} printRez(65); //газ плавно доводим до 65%, ждем, выводим результат
setthrottle(75, 1, 0); if (delayM(1000)==1){return 0;} printRez(75); //газ плавно доводим до 75%, ждем, выводим результат
setthrottle(85, 1, 0); if (delayM(1000)==1){return 0;} printRez(85); //газ плавно доводим до 85%, ждем, выводим результат
setthrottle(100, 1, 0); if (delayM(1000)==1){return 0;} printRez(100); //газ плавно доводим до 100%, ждем, выводим результат
setthrottle(0, 0, 1); //газ в ноль
}
//второй тест
if (n==2){
Serial.println("throttle from 0 to 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
for (n=0; n<100; n++){myServo.writeMicroseconds(set_pos(n)); printRez(n); if (delayM(50)==1){return 0;};} //плавный набот газа от 0% до 100% с выводом результата и возможностью прерывания процесса тестирования
Serial.println("throttle = 0%"); myServo.writeMicroseconds(set_pos(0)); //заканчиваем тест, газ в 0%
}
//третий тест
if (n==3){
Serial.println("select throttle percent or press +/- or r for print result"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//если нажат + (причем любой) наращиваем значение газа, так же присутствует вывод степени набора газа, ограничение на больше 100% и прерывание процесса тестирования
if (val==61 || val==43){if (error==1){breakTest(); return 0;}else if (throttle<=99){throttle++; setthrottle(throttle, 0, 1);}else{Serial.println("maximal throttle 100%");}}
//подобно условию выше для знака +, только теперь для знака -
else if (val==45){if (error==1){breakTest(); return 0;}else if (throttle>=1){throttle--; setthrottle(throttle, 0, 1);}else{Serial.println("minimal throttle 0%");}}
//при нажатии Enter, формируется и устанавливается уровень газа с выводом уровня установленного газа
else if (val==13){Serial.println(); error=0; throttle=strnumber.toInt(); if (throttle>=101){breakTest(); return 0;} setthrottle(throttle, 1, 1); strnumber="0";}
//тут мы формируем уровень газа путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//если в процессе работы теста нажать калвишу "r", то произойдет вывод данных датчиков
else if (val==114){printRez(throttle);}
//завершаем тест
else {breakTest(); return 0;}
}
}
}
return 0; //если нажата не "8", завершаем тест
}
//установка уровня газа
//при нулевом значении газ обрабатывается моментально, использовать только для снижения значения
//при занчении противоположном нулевому, газ будет набираться плавно
//еще добавлено одно значение для разрешения/запрета вывода результата установленного уровня газа
void setthrottle(int throttle, int x, int y){
int r = 0; //обнуляем переменную
//если значение переменной х равно 0, изменение газа происходит моментально, при любом другом, газ будет наращиваться плавно
if (x==0){
myServo.writeMicroseconds(set_pos(throttle)); //моментальное изменение газа
}else if (throttleOld>=throttle){myServo.writeMicroseconds(set_pos(throttle)); //условие для активации плавного набора газа
}else{
r = throttle - throttleOld; //просчитываем разность старого и нового значения газа для счетчика
//плавное изменение газа
for (n=0; n<r; n++){
myServo.writeMicroseconds(set_pos(throttleOld+n)); //изменяем уровень газа
if (delayM(30)==1){return;} //задержка и возможность прекращение теста по нажатию на клавишу
}
}
if (y==1){Serial.print("throttle = "); Serial.print(throttle); Serial.println("%");} //еслт y имеет значение 1, выводим результаты значения газа
throttleOld=throttle; //формируем старые показания уровня газа
return; //выход из подпрограммы
}
//функция прерывания теста, выводим сообщение о прерывании, ставим значение уровня газа в 0, обнуляем переменные
void breakTest(){
Serial.println("throttle = 0%");
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r break");
throttle=0; strnumber="0"; throttleOld=0;
return;
}
//функция задержки с возможностью прерывания
int delayM(int m){
int k;
for (k=0; k<m; k++){
if (!(Serial.available())){}else{k = 1; breakTest(); return k;}
delay(1);
}
k = 0;
return k;
}
//функция калибровки для уровня газа (еще не готова)
void servaC(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - 100%");
Serial.println("0 - 0%");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (1){
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){
myServo.writeMicroseconds(set_pos(100));
myServo.attach(servoPin, servoMinImp, servoMaxImp);
Serial.println("\n\r 100% ok");
}
if (val==48){
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r 0% ok");
}
if (val==49 || val==48){}else{return;}
}
}
//формирование меню калибровок
void beginCalibrate(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - calibration weight");
Serial.println("2 - calibration voltage");
Serial.println("3 - calibration curent");
Serial.println("4 - calibration ESC");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){Serial.println("\n\r 1 ok");}
if (val==50){Serial.println("\n\r 2 ok");}
if (val==51){Serial.println("\n\r 3 ok");}
if (val==52){servaC();}
Serial.println("\n\r stop calibration return to console");
return;
}
//чтение данных тяги
int32_t getSensorValueWeight() {
digitalWrite(SCLK, LOW); // wake up ADC
while (digitalRead(DATA) == HIGH); // wait for data ready, stay in while-loop until LOW
Weight = shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
digitalWrite(SCLK, HIGH); // enter sleep mode
Weight = ((signed long) (Weight << 8)) >> 8; // process as int24_t (two's compliment 24bit)
return Weight;
}
//результат по тяге
int weightRez(){
Weight = (getSensorValueWeight() - WeightNull)/204.6615;
return Weight;
}
//результат по напряжению
float voltageRez(){
//расчет данных напряжения
VoltageValue = analogRead(VoltPin); // считываем значение аналогового входа (напряжение)
VoltageValue = VoltageValue*0.0298217;
return VoltageValue;
}
//результат по току
float currentRez(){
//расчет данных тока
CurrentValue = analogRead(CurrPin); // считываем значение аналогового входа (ток)
CurrentValueRes = (CurrentValue-CountNull)*ISensor/512; //формула расчета тока для двунаправленнх датчиков ACS758
//CurrentValueRes = CurrentValue*ISensor/1024; //формула расчета тока для однонаправленных датчиков ACS758
return CurrentValueRes;
}
//выводим результаты датчиков, переменная v для уровня газа
void printRez(int v){
//выводим результат
Serial.print(v);
Serial.print("\t");
Serial.print(weightRez());
Serial.print("\t");
Serial.print(voltageRez());
Serial.print("\t");
Serial.println(currentRez());
Serial.flush();
}
//начало программы
void loop()
{
Serial.println();
("Helow my friend!");
Serial.println("Please type the comands:");
Serial.println("test, calibration, null, setup");
Serial.println();
Serial.print(">");
while (!(Serial.available()));
String myString = readText(60);
if (myString=="test"){Serial.println(); beginTest(); error = 0;}
if (myString=="setup"){Serial.println("\n\r setup ok"); error = 0;}
if (myString=="calibration"){Serial.println(); beginCalibrate(); error = 0;}
if (myString=="null"){Serial.println("\n\r null ok"); error = 0;}
if (myString==""){Serial.println(); error = 0;}
if (error==0){error=1;}else{Serial.println("\n\r incorrect command");}
}
все, закончил 😃
осталось поставить на стенд и проверить работу
если получится, протестирую в выходные
#include <EEPROM2.h> //подключаем библиотеку EEPROM2
#include <Servo.h> // добавляем библиотеку для работы с сервоприводами
//объявление переменных
//подключаемые разьемы на ардуине
#define servoPin 3 // для дальнейшей работы назовем 3 пин как servoPin
int DATA = 4; //пин D4 подключаем АЦП тяги
int SCLK = 5; //пин D5 подключаем АЦП тяги
int PWDN = 6; //пин D6 подключаем АЦП тяги
#define CurrPin A0 //пин A0 датчик тока
#define VoltPin A1 //пин A1 датчик напряжения
#define servoMinImp 544 // 544 это стандартная длина импульса при котором сервопривод должен принять положение 0°
#define servoMaxImp 2400 // 2400 это эталонная длина импульса при котором сервопривод должен принять положение 180°
//переменные для работы
unsigned long volt; //четырех байтная переменная для хранения в памяти
unsigned long amper; //четырех байтная переменная для хранения в памяти
unsigned long gramm; //четырех байтная переменная для хранения в памяти
float grammT = 0;
int32_t grammM = 0;
float voltT = 0;
int32_t voltM = 0;
float amperT = 0;
int32_t amperM = 0;
float CurrentValue = 0; //переменная для расчета тока (с плавающей точкой)
float CurrentValueRes = 0; //переменная с результатом для расчета тока (с плавающей точкой)
float VoltageValue = 0; //переменная для расчета напряжения (с плавающей точкой)
int32_t Weight = 0; //переменная для расчета тяги (32 разряда)
int val; //здесь будет храниться принятый символ
int n; //рабочая переменная
int error = 0; //так же рабочая переменная
int throttle = 0; //переменная газа
String strnumber = "0"; //переменная для временных текствых значаний
int throttleOld = 0; //переменная для хранения временных значений газа
//переменные для нулевых значений
int32_t WeightNull = 0; //нулевое значение по весу (переменная калибруется при включении)
int CountNull = 0; //нулевое значение по току, данная переменная для однонаправленных датчиков ACS758 (с буквой U) не используется (переменная калибруется при включении)
//эти переменные заполняются пользователем
int ISensor = 200; //максимальное значение измеряемое датчиком (смотрим даташит по ним)
Servo myServo;
//инициализация
void setup() {
//инициализация I/O
pinMode(DATA, INPUT);
pinMode(SCLK, OUTPUT);
pinMode(PWDN, OUTPUT);
digitalWrite(PWDN, HIGH);
Serial.begin(9600); //скорость порта
myServo.attach(servoPin, servoMinImp, servoMaxImp);
// устанавливаем пин как вывод управления сервоприводом,
// а также для работы сервопривода непосредственно в диапазоне углов от 0 до 180° задаем мин и макс значения импульсов.
// импульсы с большей или меньшей длиной восприниматься не будут.
// для сервоприводов даже одной партии значения длин импульсов могут отличаться, может быть даже и 584-2440.
// поэкспериментируйте и найдите идеальные длины импульсов конкретно для вашего сервопривода.
myServo.writeMicroseconds(set_pos(0)); //газ в ноль при включении
}
//чтение вводимой строки из терминала
//нахождение в цыкле пока не будет нажат ENTER или набранно определенное количество символов
//возвращает набранную строку
String readText(int n){
int i = 0; //временная целая переменная
String str; //временная строковая переменная
//собираем заданное количество символов
while (i<n) {
while (!(Serial.available())); //ждем символ
val = Serial.read(); //дождавшись, читаем его
if (val==13){return str;} //если нажат Enter, прекращаем ввод символов и передаем набранную строку
Serial.print(char(val)); //показываем нажатую клавишу на терминале
str += char(val); //формируем строку
i++; //наращиваем переменную
}
return str; //передаем набранную строку заданной длины
}
// Функция устанавливает стик газа
//диапазон желательно указывать от 0 до 100
int set_pos(int pos) {
int tmp=(servoMaxImp - servoMinImp) /100;
pos = servoMinImp + tmp * pos;
return pos;
}
//вывод меню для начала теста
//предоставление выбора типа проводимого теста
void beginTest(){
//вывод меню выбора
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - begin auto test 50, 65, 75, 85, 100%");
Serial.println("2 - begin auto test 1-100%");
Serial.println("3 - begin manual test");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//по результатам выбора начинаем тест или переходим в консоль
if (val==49){test(1);} //переход на тест с указанием номера теста 1
if (val==50){test(2);} //переход на тест с указанием номера теста 2
if (val==51){test(3);} //переход на тест с указанием номера теста 3
Serial.println("\n\r stop test return to console"); return; //возвращаем в консоль
}
//начало теста
//в зависимости от выбора, запускается тест ВМГ
int test(int n){
//ждем нажатие подтверждения начала тестов
Serial.println("\n\r============= Select action: =============");
Serial.println("8 - begin test");
Serial.println("any key - stop test and return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//если подтверждение нажато, начинаем тест, иначе выходим в консоль
if (val==56){
Serial.println("\n\r start test"); Serial.println(); //информируем о начале теста
//первый тест
if (n==1){
Serial.println("set throttle 50% 65% 75% 85% 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
Serial.println("\n\r%\tg\tv\ta"); //формируем шапку для вывода результатов
setthrottle(50, 1, 0); if (delayM(1000)==1){return 0;} printRez(50); //газ плавно доводим до 50%, ждем, выводим результат
setthrottle(65, 1, 0); if (delayM(1000)==1){return 0;} printRez(65); //газ плавно доводим до 65%, ждем, выводим результат
setthrottle(75, 1, 0); if (delayM(1000)==1){return 0;} printRez(75); //газ плавно доводим до 75%, ждем, выводим результат
setthrottle(85, 1, 0); if (delayM(1000)==1){return 0;} printRez(85); //газ плавно доводим до 85%, ждем, выводим результат
setthrottle(100, 1, 0); if (delayM(1000)==1){return 0;} printRez(100); //газ плавно доводим до 100%, ждем, выводим результат
setthrottle(0, 0, 1); //газ в ноль
}
//второй тест
if (n==2){
Serial.println("throttle from 0 to 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
Serial.println("\n\r%\tg\tv\ta"); //формируем шапку для вывода результатов
for (n=0; n<100; n++){myServo.writeMicroseconds(set_pos(n)); printRez(n); if (delayM(50)==1){return 0;};} //плавный набот газа от 0% до 100% с выводом результата и возможностью прерывания процесса тестирования
Serial.println("throttle = 0%"); myServo.writeMicroseconds(set_pos(0)); //заканчиваем тест, газ в 0%
}
//третий тест
if (n==3){
Serial.println("select throttle percent or press +/- or r for print result"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//если нажат + (причем любой) наращиваем значение газа, так же присутствует вывод степени набора газа, ограничение на больше 100% и прерывание процесса тестирования
if (val==61 || val==43){if (error==1){breakTest(); return 0;}else if (throttle<=99){throttle++; setthrottle(throttle, 0, 1);}else{Serial.println("maximal throttle 100%");}}
//подобно условию выше для знака +, только теперь для знака -
else if (val==45){if (error==1){breakTest(); return 0;}else if (throttle>=1){throttle--; setthrottle(throttle, 0, 1);}else{Serial.println("minimal throttle 0%");}}
//при нажатии Enter, формируется и устанавливается уровень газа с выводом уровня установленного газа
else if (val==13){Serial.println(); error=0; throttle=strnumber.toInt(); if (throttle>=101){breakTest(); return 0;} setthrottle(throttle, 1, 1); strnumber="0";}
//тут мы формируем уровень газа путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//если в процессе работы теста нажать калвишу "r", то произойдет вывод данных датчиков
else if (val==114){Serial.println("\n\r%\tg\tv\ta"); printRez(throttle);}
//завершаем тест
else {breakTest(); return 0;}
}
}
}
return 0; //если нажата не "8", завершаем тест
}
//установка уровня газа
//при нулевом значении газ обрабатывается моментально, использовать только для снижения значения
//при занчении противоположном нулевому, газ будет набираться плавно
//еще добавлено одно значение для разрешения/запрета вывода результата установленного уровня газа
void setthrottle(int throttle, int x, int y){
int r = 0; //обнуляем переменную
//если значение переменной х равно 0, изменение газа происходит моментально, при любом другом, газ будет наращиваться плавно
if (x==0){
myServo.writeMicroseconds(set_pos(throttle)); //моментальное изменение газа
}else if (throttleOld>=throttle){myServo.writeMicroseconds(set_pos(throttle)); //условие для активации плавного набора газа
}else{
r = throttle - throttleOld; //просчитываем разность старого и нового значения газа для счетчика
//плавное изменение газа
for (n=0; n<r; n++){
myServo.writeMicroseconds(set_pos(throttleOld+n)); //изменяем уровень газа
if (delayM(30)==1){return;} //задержка и возможность прекращение теста по нажатию на клавишу
}
}
if (y==1){Serial.print("throttle = "); Serial.print(throttle); Serial.println("%");} //еслт y имеет значение 1, выводим результаты значения газа
throttleOld=throttle; //формируем старые показания уровня газа
return; //выход из подпрограммы
}
//функция прерывания теста, выводим сообщение о прерывании, ставим значение уровня газа в 0, обнуляем переменные
void breakTest(){
Serial.println("throttle = 0%");
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r break");
throttle=0; strnumber="0"; throttleOld=0;
return;
}
//функция задержки с возможностью прерывания
int delayM(int m){
int k;
for (k=0; k<m; k++){
if (!(Serial.available())){}else{k = 1; breakTest(); return k;}
delay(1);
}
k = 0;
return k;
}
//функция калибровки для уровня газа (еще не готова)
void servaC(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - 100%");
Serial.println("0 - 0%");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (1){
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){
myServo.writeMicroseconds(set_pos(100));
myServo.attach(servoPin, servoMinImp, servoMaxImp);
Serial.println("\n\r 100% ok");
}
if (val==48){
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r 0% ok");
}
if (val==49 || val==48){}else{return;}
}
}
//формирование меню калибровок
void beginCalibrate(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - calibration weight");
Serial.println("2 - calibration voltage");
Serial.println("3 - calibration curent");
Serial.println("4 - calibration ESC");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){weightC();}
if (val==50){voltC();}
if (val==51){amperC();}
if (val==52){servaC();}
Serial.println("\n\r stop calibration return to console");
return;
}
void weightC(){
Serial.println("put standard and set weight"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//при нажатии Enter
if (val==13){Serial.println(); error=0; grammT=strnumber.toInt(); strnumber="0"; grammM=((getSensorValueWeight() - WeightNull)/grammT)*1000000; EEPROM_write(15, grammM); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {return;}
}
}
void voltC(){
Serial.println("connect standard and set real volt"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//при нажатии Enter
if (val==13){Serial.println(); error=0; voltT=strnumber.toInt(); strnumber="0"; voltM=voltT/analogRead(VoltPin)/100*1000000; EEPROM_write(0, voltM); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {return;}
}
}
void amperC(){
Serial.println("connect standard and set real current"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//если нажат + (причем любой) наращиваем значение газа, так же присутствует вывод степени набора газа, ограничение на больше 100% и прерывание процесса тестирования
if (val==61 || val==43){if (error==1){breakTest(); return;}else if (throttle<=99){throttle++; setthrottle(throttle, 0, 1);}else{Serial.println("maximal throttle 100%");}}
//подобно условию выше для знака +, только теперь для знака -
else if (val==45){if (error==1){breakTest(); return;}else if (throttle>=1){throttle--; setthrottle(throttle, 0, 1);}else{Serial.println("minimal throttle 0%");}}
//при нажатии Enter
else if (val==13){Serial.println(); error=0; amperT=strnumber.toInt(); strnumber="0"; amperM=amperT/(analogRead(CurrPin)-CountNull)/1000*1000000; EEPROM_write(7, amperM); breakTest(); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {breakTest(); return;}
}
}
//чтение данных тяги
int32_t getSensorValueWeight() {
digitalWrite(SCLK, LOW); // wake up ADC
while (digitalRead(DATA) == HIGH); // wait for data ready, stay in while-loop until LOW
Weight = shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
digitalWrite(SCLK, HIGH); // enter sleep mode
Weight = ((signed long) (Weight << 8)) >> 8; // process as int24_t (two's compliment 24bit)
return Weight;
}
//результат по тяге
int weightRez(){
Weight = (getSensorValueWeight() - WeightNull)/grammT;;
return Weight;
}
//результат по напряжению
float voltageRez(){
//расчет данных напряжения
VoltageValue = analogRead(VoltPin); // считываем значение аналогового входа (напряжение)
VoltageValue = VoltageValue*voltT; ;
return VoltageValue;
}
//результат по току
float currentRez(){
//расчет данных тока
CurrentValue = analogRead(CurrPin); // считываем значение аналогового входа (ток)
CurrentValueRes = (CurrentValue-CountNull)*amperT;
//CurrentValueRes = (CurrentValue-CountNull)*ISensor/512; //формула расчета тока для двунаправленнх датчиков ACS758
//CurrentValueRes = CurrentValue*ISensor/1024; //формула расчета тока для однонаправленных датчиков ACS758
return CurrentValueRes;
}
//выводим результаты датчиков, переменная v для уровня газа
void printRez(int v){
//выводим результат
Serial.print(v);
Serial.print("\t");
Serial.print(weightRez());
Serial.print("\t");
Serial.print(voltageRez());
Serial.print("\t");
Serial.println(currentRez());
Serial.flush();
}
void nullF(){
//читаем нулевые значения по весу и току (обнуляем)
WeightNull = getSensorValueWeight();
CountNull = analogRead(CurrPin);
EEPROM_write(23, WeightNull);
EEPROM_write(31, CountNull);
Serial.println("\n\r zero value of the set");
}
//начало программы
void loop()
{
EEPROM_read(0, volt); //читаем из пямяти переменную
EEPROM_read(7, amper); //читаем из пямяти переменную
EEPROM_read(15, gramm); //читаем из пямяти переменную
voltT = (float)volt/1000000;
amperT = (float)amper/1000000; (amper);
grammT = (float)gramm/1000000;
EEPROM_read(23, WeightNull);
EEPROM_read(31, CountNull);
Serial.println();
Serial.println("\n\r%\tg\tv\ta"); printRez(0);
Serial.println();
("Helow my friend!");
Serial.println("Please type the comands:");
Serial.println("test, calibration, null");
Serial.println();
Serial.print(">");
while (!(Serial.available()));
String myString = readText(60);
if (myString=="test" || myString=="t"){Serial.println(); beginTest(); error = 0;}
//if (myString=="setup"){Serial.println("\n\r setup ok"); error = 0;}
if (myString=="calibration" || myString=="c"){Serial.println(); beginCalibrate(); error = 0;}
if (myString=="null" || myString=="n"){nullF(); error = 0;}
if (myString==""){Serial.println(); error = 0;}
if (error==0){error=1;}else{Serial.println("\n\r incorrect command");}
}
добавлено калибровка тяги, тока, напряжения и регулей
установка нулевых уровней для тока и тяги
все значения сохраняются в энергонезависимую память
заказал для стенда новую платку АЦП
и более чувствительный датчик тока
ЗЫ осталось самое сложное, написать документацию 😃
float CurrentValueRes = 0.0f; // переменная с результатом для расчета тока (с плавающей точкой)
А то могут и непонятки начаться типа вместо 1 будет 0.999998…
результаты пробного тестирования, как и ожидалось, дело осталось за фильтром
% g v a
0 4 4.33 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 1
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
set throttle 50% 65% 75% 85% 100%
% g v a
50 471 16.46 3.54
65 735 16.16 4.73
75 942 16.13 7.68
85 1160 16.04 10.34
100 1451 15.83 15.06
throttle = 0%
stop test return to console
% g v a
0 1451 16.31 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 2
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
throttle from 0 to 100%
% g v a
0 3 16.43 0.30
1 4 16.43 0.30
2 4 16.43 0.30
3 3 16.43 0.30
4 3 16.43 1.48
5 3 16.43 0.59
6 3 16.34 0.59
7 4 16.43 0.59
8 4 16.43 0.89
9 7 16.43 0.59
10 11 16.43 0.59
11 16 16.46 0.89
12 21 16.43 0.89
13 26 16.46 0.89
14 32 16.37 0.30
15 38 16.43 0.89
16 44 16.43 0.89
17 50 16.46 1.18
18 56 16.34 0.59
19 63 16.37 0.30
20 71 16.43 1.18
21 79 16.34 0.59
22 87 16.46 0.89
23 95 16.31 0.59
24 104 16.46 1.18
25 113 16.46 1.48
26 121 16.31 0.89
27 131 16.46 1.48
28 142 16.37 1.48
29 153 16.31 1.18
30 163 16.37 0.89
31 173 16.46 1.77
32 184 16.46 1.77
33 195 16.43 2.07
34 207 16.46 2.07
35 218 16.40 1.18
36 229 16.46 2.36
37 241 16.43 2.36
38 253 16.40 2.36
39 266 16.49 2.66
40 279 16.46 2.66
41 292 16.25 2.07
42 306 16.28 2.07
43 321 16.28 2.36
44 336 16.28 2.66
45 350 16.31 2.95
46 364 16.28 3.25
47 379 16.49 3.54
48 393 16.22 2.66
49 409 16.46 3.54
50 425 16.19 2.66
51 442 16.22 2.95
52 457 16.43 3.54
53 472 16.22 2.95
54 488 16.46 4.73
55 505 16.55 5.02
56 524 16.16 3.54
57 543 16.28 5.61
58 558 16.49 5.61
59 573 16.49 5.61
60 591 16.49 5.61
61 608 16.10 4.73
62 627 16.49 6.50
63 646 16.16 4.73
64 666 16.16 5.02
65 686 16.10 5.61
66 706 16.52 7.98
67 725 16.07 5.61
68 745 16.19 7.09
69 767 16.10 6.50
70 788 16.10 6.50
71 809 16.43 8.57
72 829 16.10 9.16
73 848 16.34 6.79
74 870 16.49 9.75
75 893 16.07 8.86
76 914 16.31 7.98
77 936 16.07 7.98
78 960 16.49 8.86
79 984 16.07 10.63
80 1006 16.04 9.45
81 1029 16.01 10.04
82 1051 16.04 10.34
83 1072 15.98 10.34
84 1094 16.10 10.63
85 1118 15.98 10.63
86 1145 15.95 11.22
87 1169 16.37 11.52
88 1187 15.92 11.82
89 1208 15.89 12.41
90 1230 15.92 12.41
91 1252 15.95 12.70
92 1277 15.89 13.29
93 1300 16.16 13.88
94 1319 15.89 14.18
95 1340 15.89 14.47
96 1365 15.98 14.47
97 1390 15.83 15.95
98 1413 15.89 14.77
99 1441 15.92 16.54
throttle = 0%
stop test return to console
% g v a
0 1467 16.31 0.30
Please type the comands:
test, calibration, null
>t
incorrect command
% g v a
0 5 16.43 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 2
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
throttle from 0 to 100%
% g v a
0 5 16.43 0.30
1 5 16.43 0.30
2 4 16.43 0.30
3 5 16.43 1.18
4 4 16.43 0.59
5 4 16.43 0.59
6 4 16.43 0.59
7 4 16.43 0.59
8 5 16.40 0.59
9 8 16.46 0.89
10 13 16.46 0.89
11 18 16.43 0.59
12 23 16.46 0.89
13 28 16.46 0.89
14 33 16.43 0.89
15 39 16.37 0.30
16 45 16.43 0.89
17 52 16.34 0.30
18 58 16.43 0.89
19 66 16.43 0.89
20 73 16.46 1.18
21 81 16.34 0.59
22 89 16.46 0.89
23 97 16.43 1.18
24 106 16.46 1.18
25 115 16.37 0.89
26 124 16.46 1.77
27 134 16.28 0.89
28 145 16.31 0.89
29 155 16.46 1.77
30 165 16.28 0.89
31 176 16.37 1.18
32 187 16.37 1.48
33 197 15.98 2.07
34 208 16.28 1.18
35 220 16.46 2.36
36 232 16.25 1.18
37 246 16.46 2.36
38 259 16.25 1.48
39 272 16.31 2.07
40 285 16.43 2.36
41 300 16.46 2.95
42 315 16.46 2.95
43 330 16.43 2.95
44 344 16.31 2.36
45 359 16.34 2.66
46 373 16.28 2.95
47 387 16.22 2.36
48 401 16.46 2.36
49 415 16.46 4.14
50 430 16.46 4.43
51 446 16.49 4.14
52 462 16.49 4.43
53 477 16.46 4.73
54 494 16.49 3.84
55 512 16.16 3.25
56 530 16.37 4.43
57 548 16.37 4.73
58 564 16.13 3.84
59 582 16.10 4.43
60 602 16.49 5.91
61 623 16.10 4.43
62 642 16.13 4.43
63 659 16.49 6.50
64 679 16.13 5.32
65 699 16.16 5.61
66 719 16.46 5.91
67 739 16.10 6.20
68 759 16.16 7.09
69 780 16.10 6.50
70 800 16.10 6.50
71 821 16.19 7.98
72 842 16.31 7.09
73 862 16.13 7.98
74 883 16.28 7.68
75 904 16.40 9.45
76 927 16.07 8.27
77 947 16.01 8.57
78 968 16.28 8.86
79 991 16.07 9.16
80 1015 16.16 10.63
81 1038 16.04 10.63
82 1061 16.49 11.52
83 1083 16.01 10.34
84 1108 15.98 10.63
85 1132 16.01 10.93
86 1155 16.49 13.00
87 1177 16.34 12.41
88 1200 15.95 12.11
89 1221 15.92 12.41
90 1241 16.31 12.70
91 1264 15.89 13.29
92 1286 16.07 13.59
93 1309 15.89 13.88
94 1335 15.92 13.88
95 1359 16.01 14.47
96 1382 15.80 15.66
97 1404 15.83 15.36
98 1431 16.31 15.06
99 1464 15.86 15.06
throttle = 0%
stop test return to console
% g v a
0 1474 16.31 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 2
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
throttle from 0 to 100%
% g v a
0 6 16.40 0.30
1 6 16.40 0.30
2 6 16.40 0.30
3 6 16.43 0.89
4 6 16.40 0.89
5 6 16.43 0.59
6 6 16.40 0.89
7 6 16.40 0.59
8 7 16.34 0.30
9 9 16.31 0.59
10 13 16.37 0.59
11 17 16.31 0.30
12 22 16.40 0.59
13 28 16.43 0.89
14 33 16.43 0.89
15 39 16.31 0.89
16 45 16.43 0.89
17 51 16.40 0.89
18 58 16.34 0.59
19 65 16.40 0.30
20 72 16.40 1.18
21 80 16.37 0.30
22 89 16.40 0.59
23 97 16.40 1.48
24 105 16.40 1.48
25 113 16.43 1.48
26 121 16.43 1.77
27 130 16.28 0.59
28 138 16.40 1.48
29 148 16.43 1.77
30 158 16.25 0.89
31 168 16.25 0.89
32 178 16.40 2.07
33 189 16.37 1.48
34 199 16.43 2.07
35 208 16.22 1.18
36 218 16.31 1.77
37 230 16.46 2.07
38 241 16.46 2.66
39 254 16.43 2.66
40 268 16.22 1.48
41 282 16.43 2.66
42 297 16.19 1.77
43 312 16.40 2.95
44 328 16.19 1.77
45 342 16.19 2.07
46 354 16.43 3.54
47 367 16.25 2.95
48 382 16.19 2.36
49 397 16.31 2.95
50 411 16.37 2.95
51 427 16.19 3.25
52 442 16.43 4.14
53 456 16.43 4.14
54 472 16.46 5.02
55 489 16.16 3.84
56 506 16.16 3.54
57 524 16.16 4.14
58 541 16.13 4.14
59 558 16.43 5.61
60 574 16.07 6.50
61 591 16.16 5.02
62 608 16.07 4.73
63 627 16.19 5.02
64 649 16.19 6.20
65 671 16.07 5.32
66 692 16.46 5.61
67 713 16.10 5.91
68 731 16.04 5.91
69 752 16.46 7.98
70 772 16.10 7.68
71 794 16.04 7.09
72 814 16.04 6.50
73 835 16.04 7.09
74 856 15.98 7.98
75 876 16.10 8.27
76 895 16.04 8.27
77 917 16.01 9.75
78 939 16.28 8.57
79 961 15.98 8.86
80 986 16.16 10.34
81 1012 15.98 9.75
82 1035 15.89 9.45
83 1055 15.95 11.52
84 1076 15.92 12.11
85 1098 16.28 11.82
86 1122 15.98 12.41
87 1144 16.01 12.41
88 1162 16.10 11.82
89 1184 15.92 12.11
90 1205 15.98 13.29
91 1225 16.13 14.18
92 1245 16.13 12.70
93 1269 15.89 13.88
94 1290 16.22 13.59
95 1310 15.95 14.47
96 1330 15.89 14.47
97 1353 15.92 15.66
98 1376 15.86 15.06
99 1404 15.89 15.95
throttle = 0%
stop test return to console
% g v a
0 1433 16.28 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 2
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
throttle from 0 to 100%
% g v a
0 7 16.37 0.30
1 7 16.37 0.30
2 7 16.40 0.30
3 7 16.40 0.30
4 7 16.43 0.89
5 7 16.28 0.59
6 7 16.37 0.59
7 7 16.34 0.59
8 7 16.37 0.59
9 9 16.40 0.59
10 13 16.37 0.59
11 17 16.40 0.89
12 22 16.40 0.89
13 27 16.40 0.89
14 32 16.31 0.59
15 37 16.31 0.59
16 43 16.40 0.59
17 50 16.40 1.18
18 56 16.40 1.18
19 63 16.34 0.89
20 70 16.40 1.18
21 77 16.40 1.18
22 85 16.40 0.89
23 92 16.40 1.18
24 100 16.40 1.48
25 109 16.40 1.18
26 118 16.28 1.18
27 129 16.40 1.77
28 139 16.28 0.89
29 148 16.43 1.77
30 158 16.40 1.77
31 168 16.25 0.89
32 179 16.49 2.07
33 189 16.25 1.18
34 199 16.40 1.18
35 210 16.40 2.07
36 222 16.37 1.48
37 234 16.25 1.77
38 248 16.43 2.36
39 260 16.25 2.07
40 274 16.40 2.66
41 288 16.28 2.66
42 303 16.43 2.95
43 318 16.43 3.25
44 332 16.19 2.36
45 346 16.43 3.25
46 360 16.28 2.07
47 374 16.31 3.25
48 387 16.43 3.84
49 402 16.43 4.14
50 417 16.19 2.66
51 431 16.40 4.14
52 447 16.19 3.54
53 463 16.46 2.95
54 480 16.19 4.14
55 496 16.25 4.73
56 513 16.10 3.84
57 531 16.19 3.84
58 549 16.46 5.32
59 566 16.13 4.14
60 583 16.43 5.91
61 599 16.43 6.20
62 616 16.37 6.50
63 634 16.43 6.50
64 654 16.19 5.61
65 673 16.13 5.91
66 691 16.10 5.32
67 710 16.10 7.68
68 729 16.10 7.98
69 749 16.10 6.79
70 770 16.04 6.79
71 791 16.04 7.09
72 812 16.22 6.79
73 834 16.28 7.09
74 857 16.04 7.38
75 878 16.07 7.38
76 899 16.04 8.57
77 924 16.04 9.45
78 947 16.13 8.27
79 967 16.34 8.86
80 987 15.98 9.75
81 1007 15.95 9.16
82 1029 15.98 11.22
83 1051 15.92 10.04
84 1073 15.92 12.11
85 1093 15.95 10.63
86 1113 15.92 11.22
87 1136 15.95 11.22
88 1159 15.89 11.82
89 1184 15.92 11.82
90 1205 15.89 12.41
91 1225 15.89 13.59
92 1246 15.92 13.88
93 1263 15.86 13.29
94 1284 15.89 14.18
95 1306 15.89 14.47
96 1330 15.86 14.47
97 1353 15.83 15.66
98 1375 15.83 17.43
99 1406 16.31 15.06
throttle = 0%
stop test return to console
% g v a
0 1435 16.28 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 1
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
set throttle 50% 65% 75% 85% 100%
% g v a
50 448 16.25 2.95
65 703 16.10 5.32
75 904 16.04 6.79
85 1129 16.01 11.52
100 1432 15.77 14.77
throttle = 0%
stop test return to console
% g v a
0 1429 16.25 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 1
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
set throttle 50% 65% 75% 85% 100%
% g v a
50 443 16.34 3.54
65 705 16.07 4.73
75 899 15.98 6.79
85 1109 15.92 10.63
100 1425 15.77 14.77
throttle = 0%
stop test return to console
% g v a
0 1429 16.22 0.30
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 1
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
set throttle 50% 65% 75% 85% 100%
% g v a
50 441 16.10 2.36
65 696 16.01 4.43
75 892 16.13 8.86
85 1105 16.34 9.75
100 1409 15.80 15.66
throttle = 0%
stop test return to console
% g v a
0 1412 16.19 0.30
Please type the comands:
test, calibration, null
>
ЗЫ фильтр будет один из этих, остались с предыдущих моих перлов программирования на STM32
(найдены на просторах всемирной 😃)
//фильтр простой
int filter(int y, int r)
{
int z=(15*y+r)>>4;
return z;
}
//фильтр чуть сложнее
uint filter_1(uint x1, uint Nb1, uint k1){
static uint y1 = 0;
static uint z1 = 0;
z1 += (x1 - y1);
return y1 = (Nb1 * z1) >> k1;
}
Александр, эт вы на чём тестили двиг/проп - 400гр. тяги на 50%? почти 8гр/ватт
Александр, эт вы на чём тестили двиг/проп - 400гр. тяги на 50%? почти 8гр/ватт
это СанниСкаи 3508 580 с АПЦ 1238
прикрутил фильтр, требуется помощь по решению проблемы запаздывания у фильтра, у кого есть какие соображения?
на картинке показания напряжения и тока до (синий) и после фильтра (красный)
может тупо делать умножение показаний на коэффициент? 😃
например вот показания тока без множителя и с множителем 1,4
пример точности повторных измерений
графики по порядку
напряжение, ток, тяга
тестировалось на одном аккумуляторе 3S 4А, СС 3508 580, АПС 1238, три теста подряд
видно как просаживается аккумулятор во время теста
следует использовать несколько паков в параллель, что бы избежать просадки
полностью результаты теста
колонки по порядку
% тяги, тяга как есть, напряжение как есть, напряжение с фильтром и коэффициентом, ток как есть, ток с фильтром и коэффициентом
% g v v+f+* a a+f+*
0 0 4.30 4.30 0.29 0.44
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 2
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
throttle from 0 to 100%
% g v v+f+* a a+f+*
0 0 12.33 12.33 0.29 0.44
1 0 12.33 12.33 0.29 0.44
2 0 12.33 12.33 0.29 0.44
3 0 12.33 12.33 0.59 0.44
4 0 12.33 12.33 0.59 0.45
5 0 12.33 12.32 0.59 0.46
6 0 12.27 12.31 0.59 0.48
7 0 12.33 12.31 0.59 0.50
8 0 12.33 12.31 0.29 0.50
9 0 12.33 12.31 0.59 0.50
10 0 12.30 12.30 0.59 0.51
11 0 12.33 12.30 0.59 0.52
12 0 12.33 12.30 0.59 0.54
13 0 12.33 12.29 0.29 0.54
14 0 12.27 12.28 0.59 0.54
15 0 12.33 12.28 0.59 0.55
16 0 12.30 12.28 0.29 0.55
17 0 12.30 12.28 0.59 0.55
18 0 12.33 12.28 0.59 0.57
19 0 12.33 12.28 0.59 0.58
20 0 12.33 12.28 0.88 0.60
21 1 12.33 12.27 0.88 0.65
22 4 12.30 12.27 0.59 0.67
23 9 12.30 12.27 0.88 0.67
24 13 12.30 12.27 0.59 0.70
25 18 12.24 12.26 0.88 0.70
26 23 12.33 12.26 0.59 0.74
27 28 12.33 12.26 1.18 0.74
28 33 12.24 12.25 0.88 0.79
29 39 12.33 12.24 1.18 0.83
30 45 12.30 12.24 1.18 0.87
31 50 12.33 12.24 0.88 0.91
32 56 12.33 12.24 1.47 0.93
33 63 12.33 12.24 1.18 1.00
34 70 12.33 12.24 0.88 1.05
35 77 12.33 12.24 0.88 1.06
36 85 12.27 12.23 0.88 1.08
37 92 12.24 12.21 1.18 1.10
38 100 12.30 12.21 1.47 1.12
39 107 12.18 12.20 1.47 1.19
40 114 12.33 12.20 1.47 1.25
41 122 12.21 12.19 1.77 1.31
42 130 12.30 12.19 1.77 1.38
43 138 12.33 12.19 1.47 1.46
44 148 12.30 12.19 2.06 1.50
45 157 12.33 12.18 1.47 1.59
46 165 12.24 12.18 1.47 1.62
47 173 12.18 12.17 2.36 1.65
48 182 12.24 12.17 1.47 1.75
49 190 12.27 12.17 2.65 1.77
50 198 12.30 12.17 2.36 1.90
51 208 12.21 12.16 1.77 2.00
52 218 12.15 12.15 2.65 2.03
53 229 12.30 12.15 2.65 2.15
54 240 12.30 12.14 2.95 2.25
55 250 12.30 12.14 2.95 2.39
56 261 12.18 12.13 2.36 2.50
57 271 12.18 12.12 2.95 2.57
58 283 12.12 12.11 2.65 2.67
59 294 12.06 12.10 2.95 2.75
60 304 12.30 12.10 2.95 2.85
61 315 12.30 12.10 3.24 2.94
62 327 12.30 12.09 3.54 3.06
63 338 12.06 12.08 3.24 3.20
64 350 12.12 12.07 3.24 3.29
65 362 12.30 12.07 4.13 3.38
66 374 12.27 12.07 4.43 3.54
67 385 12.09 12.06 3.24 3.72
68 397 12.06 12.05 3.83 3.78
69 409 12.09 12.04 4.13 3.90
70 422 12.21 12.04 4.72 4.03
71 435 12.12 12.03 4.13 4.22
72 448 12.03 12.02 5.02 4.34
73 461 12.03 12.01 4.43 4.53
74 474 12.27 12.02 5.02 4.65
75 486 12.03 12.01 4.43 4.83
76 500 12.00 12.00 5.02 4.94
77 512 12.24 12.00 5.90 5.09
78 526 11.97 11.99 5.31 5.31
79 541 12.00 11.97 5.61 5.48
80 557 12.00 11.96 5.31 5.65
81 572 12.00 11.95 6.20 5.79
82 587 12.09 11.95 6.79 6.02
83 601 11.97 11.94 7.08 6.27
84 615 12.06 11.94 6.20 6.52
85 630 11.97 11.93 6.79 6.69
86 645 12.24 11.94 7.38 6.92
87 661 12.15 11.94 7.08 7.15
88 677 11.94 11.92 7.38 7.36
89 692 11.97 11.91 7.08 7.59
90 708 11.88 11.90 7.97 7.78
91 724 11.88 11.89 9.45 8.04
92 739 11.91 11.88 7.97 8.40
93 753 11.88 11.87 8.56 8.63
94 766 12.12 11.87 8.27 8.86
95 782 11.88 11.86 8.86 9.09
96 797 11.83 11.85 9.74 9.35
97 815 11.88 11.83 9.45 9.67
98 837 11.85 11.82 9.15 9.93
99 860 11.85 11.81 9.15 10.15
throttle = 0%
stop test return to console
% g v v+f+* a a+f+*
0 870 12.24 12.24 0.29 0.44
Please type the comands:
test, calibration, null
>test
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 3
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select
stop test return to console
% g v v+f+* a a+f+*
0 -1 12.30 12.30 0.29 0.44
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 2
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
throttle from 0 to 100%
% g v v+f+* a a+f+*
0 -1 12.30 12.30 0.29 0.44
1 -1 12.30 12.30 0.29 0.44
2 -1 12.30 12.30 0.29 0.44
3 -1 12.30 12.30 0.59 0.44
4 -1 12.27 12.29 0.88 0.45
5 -1 12.30 12.28 0.59 0.50
6 -1 12.30 12.28 0.29 0.50
7 -1 12.30 12.28 0.59 0.50
8 -1 12.30 12.28 0.59 0.51
9 -1 12.30 12.28 0.59 0.52
10 -1 12.27 12.27 0.59 0.54
11 -1 12.30 12.27 0.59 0.55
12 -1 12.27 12.26 0.59 0.57
13 -1 12.30 12.25 0.59 0.58
14 -1 12.30 12.25 0.59 0.60
15 -1 12.30 12.25 0.59 0.61
16 -1 12.30 12.25 0.59 0.63
17 -1 12.30 12.25 0.59 0.65
18 -1 12.30 12.25 0.88 0.66
19 -1 12.27 12.25 0.88 0.69
20 -1 12.30 12.25 0.59 0.72
21 0 12.21 12.23 0.88 0.72
22 2 12.21 12.22 0.88 0.75
23 6 12.30 12.22 0.88 0.78
24 11 12.30 12.22 0.59 0.81
25 16 12.24 12.21 0.88 0.81
26 21 12.30 12.21 0.88 0.84
27 26 12.27 12.21 0.88 0.87
28 31 12.24 12.21 1.18 0.88
29 37 12.21 12.19 1.18 0.93
30 43 12.30 12.19 0.88 0.97
31 48 12.30 12.19 1.18 0.99
32 53 12.24 12.19 1.18 1.03
33 61 12.27 12.19 0.88 1.08
34 68 12.24 12.19 0.88 1.10
35 75 12.27 12.19 1.18 1.10
36 81 12.18 12.18 1.47 1.12
37 88 12.30 12.17 1.18 1.19
38 95 12.30 12.17 1.77 1.22
39 103 12.24 12.17 1.77 1.31
40 111 12.30 12.17 1.47 1.38
41 120 12.15 12.16 1.77 1.42
42 128 12.30 12.16 1.47 1.50
43 136 12.30 12.16 1.77 1.53
44 145 12.27 12.16 1.47 1.59
45 152 12.15 12.15 1.77 1.62
46 160 12.18 12.13 2.36 1.68
47 168 12.24 12.13 2.06 1.79
48 177 12.21 12.13 1.47 1.86
49 186 12.30 12.13 2.36 1.88
50 196 12.30 12.13 1.77 1.96
51 206 12.30 12.13 2.65 2.00
52 216 12.15 12.12 1.77 2.12
53 226 12.12 12.11 2.95 2.15
54 237 12.30 12.10 2.65 2.28
55 247 12.30 12.10 2.65 2.39
56 258 12.12 12.09 2.36 2.48
57 268 12.12 12.08 2.06 2.54
58 278 12.18 12.08 2.95 2.57
59 288 12.30 12.08 2.65 2.67
60 300 12.27 12.08 3.54 2.75
61 311 12.15 12.08 2.65 2.90
62 322 12.18 12.07 2.95 2.96
63 332 12.27 12.07 3.83 3.05
64 344 12.12 12.06 3.54 3.21
65 356 12.27 12.06 3.83 3.33
66 367 12.06 12.05 3.54 3.48
67 379 12.09 12.04 2.95 3.59
68 392 12.21 12.04 4.72 3.63
69 404 12.06 12.03 3.24 3.84
70 416 12.09 12.02 4.43 3.90
71 428 12.03 12.00 4.13 4.07
72 441 12.06 11.99 5.02 4.19
73 454 12.27 12.00 5.31 4.38
74 466 12.03 11.99 4.43 4.59
75 479 12.27 12.00 5.90 4.73
76 493 12.03 11.99 5.02 4.97
77 508 12.03 11.98 4.72 5.12
78 523 12.03 11.97 5.31 5.24
79 536 12.21 11.96 5.02 5.40
80 550 12.15 11.96 6.20 5.52
81 564 11.97 11.95 5.90 5.75
82 578 12.24 11.96 5.90 5.93
83 593 11.94 11.95 6.20 6.11
84 610 12.09 11.95 6.20 6.30
85 626 12.00 11.94 6.79 6.48
86 642 11.97 11.93 6.49 6.71
87 656 11.97 11.92 6.79 6.89
88 671 11.97 11.90 7.08 7.08
89 685 11.94 11.89 7.08 7.29
90 701 11.88 11.88 7.67 7.50
91 715 11.94 11.87 7.67 7.73
92 729 12.15 11.88 7.97 7.97
93 744 12.03 11.88 8.56 8.21
94 761 11.91 11.87 8.27 8.49
95 777 12.09 11.87 8.86 8.73
96 793 11.88 11.86 8.56 9.02
97 809 11.85 11.84 10.33 9.26
98 831 11.85 11.83 9.15 9.64
99 855 11.88 11.82 9.15 9.90
throttle = 0%
stop test return to console
% g v v+f+* a a+f+*
0 865 12.24 12.24 0.29 0.44
Please type the comands:
test, calibration, null
>t
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
you select 2
============= Select action: =============
8 - begin test
any key - stop test and return to console
==========================================
you select 8
start test
throttle from 0 to 100%
% g v v+f+* a a+f+*
0 -1 12.30 12.30 0.29 0.44
1 -1 12.30 12.30 0.29 0.44
2 -1 12.30 12.30 0.29 0.44
3 -1 12.27 12.29 0.59 0.44
4 -1 12.30 12.29 0.59 0.45
5 -1 12.27 12.27 0.59 0.46
6 -1 12.30 12.27 0.59 0.48
7 -1 12.30 12.27 0.59 0.50
8 -1 12.30 12.27 0.59 0.51
9 -1 12.30 12.27 0.59 0.52
10 -1 12.30 12.27 0.59 0.54
11 -1 12.30 12.27 0.59 0.55
12 -1 12.30 12.27 0.59 0.57
13 -1 12.30 12.26 0.29 0.57
14 -1 12.30 12.26 0.59 0.57
15 -1 12.27 12.25 0.59 0.58
16 -1 12.24 12.24 0.59 0.60
17 -1 12.27 12.24 0.59 0.61
18 -1 12.24 12.23 0.59 0.63
19 -1 12.21 12.22 0.59 0.65
20 -1 12.30 12.22 0.88 0.66
21 0 12.27 12.21 0.59 0.69
22 1 12.30 12.21 0.88 0.69
23 5 12.27 12.21 0.59 0.72
24 10 12.30 12.21 0.88 0.72
25 15 12.27 12.21 0.88 0.75
26 20 12.21 12.20 0.59 0.78
27 25 12.30 12.20 1.18 0.78
28 31 12.24 12.20 0.88 0.84
29 36 12.30 12.19 1.18 0.87
30 41 12.30 12.19 1.18 0.91
31 47 12.18 12.18 1.18 0.96
32 54 12.24 12.18 1.18 1.00
33 61 12.30 12.18 1.18 1.05
34 68 12.27 12.18 0.88 1.10
35 73 12.21 12.17 0.88 1.10
36 79 12.30 12.17 1.47 1.10
37 85 12.27 12.16 0.88 1.15
38 92 12.27 12.16 1.47 1.15
39 99 12.30 12.16 1.47 1.22
40 107 12.27 12.16 1.47 1.28
41 114 12.24 12.16 1.18 1.32
42 123 12.18 12.15 1.18 1.34
43 131 12.27 12.15 1.77 1.35
44 140 12.27 12.15 1.77 1.42
45 148 12.27 12.15 1.18 1.50
46 157 12.12 12.13 2.06 1.51
47 165 12.15 12.12 2.06 1.61
48 174 12.21 12.12 1.47 1.69
49 183 12.21 12.12 2.06 1.72
50 191 12.27 12.12 1.77 1.80
51 201 12.27 12.12 2.65 1.85
52 211 12.27 12.12 2.65 1.96
53 222 12.15 12.11 1.77 2.09
54 233 12.15 12.09 2.06 2.12
55 243 12.09 12.08 2.65 2.18
56 253 12.27 12.08 3.24 2.28
57 263 12.15 12.08 2.65 2.43
58 274 12.18 12.08 2.36 2.52
59 284 12.15 12.08 2.95 2.58
60 294 12.09 12.07 3.24 2.69
61 304 12.06 12.06 2.65 2.82
62 315 12.06 12.04 2.65 2.88
63 326 12.06 12.03 2.65 2.94
64 337 12.24 12.03 4.13 3.00
65 348 12.27 12.04 3.83 3.20
66 360 12.18 12.04 4.43 3.35
67 374 12.24 12.04 4.43 3.54
68 387 12.09 12.03 3.83 3.72
69 398 12.06 12.02 4.13 3.84
70 409 12.06 12.01 3.54 3.98
71 421 12.00 11.99 4.13 4.05
72 432 12.03 11.98 4.13 4.17
73 446 11.97 11.97 4.72 4.29
74 460 12.06 11.97 4.43 4.46
75 473 12.06 11.97 4.13 4.59
76 485 12.15 11.97 5.02 4.68
77 498 12.00 11.96 4.72 4.85
78 512 11.97 11.95 5.90 5.00
79 525 11.97 11.93 5.61 5.22
80 540 11.97 11.92 6.20 5.43
81 555 12.15 11.92 5.90 5.65
82 569 12.15 11.92 5.90 5.85
83 583 12.15 11.92 7.38 6.05
84 597 11.97 11.91 6.20 6.35
85 614 11.97 11.90 5.90 6.52
86 630 12.03 11.90 7.97 6.67
87 644 12.21 11.91 6.49 6.99
88 660 11.94 11.89 7.38 7.17
89 677 11.88 11.88 7.38 7.39
90 693 12.06 11.88 7.38 7.62
91 710 11.88 11.87 7.97 7.85
92 725 11.91 11.86 7.67 8.09
93 741 11.88 11.85 8.27 8.31
94 757 11.88 11.84 8.86 8.57
95 773 11.85 11.83 7.97 8.84
96 790 11.83 11.82 10.04 9.05
97 806 11.85 11.80 9.45 9.42
98 829 11.94 11.80 9.15 9.71
99 857 11.85 11.79 9.15 9.93
throttle = 0%
stop test return to console
% g v v+f+* a a+f+*
0 870 11.85 11.85 0.29 0.44
Please type the comands:
test, calibration, null
ЗЫ еще пару графиков мощность и эффективность ВМГ
Под настроил стенд более точно, на сколько это возможно (датчик тока очень не подходящий, скоро будут нужные)
Обработанные данные со стенда (4 теста подряд, среднее значение):
мотор - SunnySky V3508-20 KV580
пропеллер - APC 12x8 Slo-flyer Propeller
аккумулятор - ZIPPY Compact 4000mAh 4S 25C (3 пака в параллель)
регулятор - SK-30A SimonK Firmware Multicopter Speed Controller ESC 30A
тяга
напряжение
ток
мощность
эффективность
% g v a w e
============================================
0 4 16.62 0.00 0 0.00
1 4 16.62 0.00 0 0.00
2 4 16.62 0.00 0 0.00
3 4 16.62 0.00 0 0.00
4 4 16.61 0.00 0 0.00
5 4 16.61 0.07 1 3.57
6 4 16.61 0.08 1 4.15
7 7 16.61 0.09 1 4.68
8 9 16.61 0.12 2 4.75
9 12 16.60 0.13 2 5.69
10 17 16.59 0.15 2 6.31
11 23 16.59 0.16 3 7.76
12 28 16.59 0.19 3 7.78
13 33 16.58 0.19 3 8.76
14 38 16.57 0.20 3 10.03
15 44 16.57 0.23 4 9.98
16 50 16.56 0.25 4 10.06
17 55 16.56 0.28 5 10.48
18 62 16.56 0.30 5 10.99
19 69 16.56 0.33 5 11.23
20 77 16.56 0.37 6 11.26
21 85 16.55 0.40 7 11.44
22 92 16.54 0.45 7 11.63
23 100 16.54 0.48 8 11.81
24 109 16.53 0.52 9 12.16
25 118 16.53 0.55 9 12.66
26 127 16.53 0.57 9 13.11
27 137 16.53 0.62 10 13.07
28 146 16.52 0.67 11 12.78
29 156 16.52 0.71 12 13.08
30 166 16.52 0.77 13 13.01
31 177 16.51 0.82 13 13.06
32 187 16.51 0.88 14 12.86
33 198 16.51 0.92 15 13.11
34 209 16.50 0.98 16 13.06
35 221 16.49 1.02 17 13.06
36 233 16.49 1.07 18 13.04
37 246 16.49 1.16 19 12.72
38 259 16.49 1.23 20 12.45
39 273 16.48 1.30 21 12.63
40 286 16.47 1.38 23 12.48
41 300 16.47 1.48 24 12.34
42 315 16.47 1.59 26 12.05
43 331 16.47 1.69 28 11.90
44 347 16.46 1.78 29 11.77
45 362 16.46 1.89 31 11.66
46 378 16.45 1.99 33 11.77
47 394 16.45 2.14 35 11.28
48 410 16.45 2.23 37 11.28
49 426 16.44 2.38 39 11.00
50 443 16.43 2.47 41 10.96
51 460 16.43 2.59 43 10.92
52 477 16.42 2.75 45 10.66
53 494 16.41 2.90 48 10.44
54 512 16.42 3.02 49 10.32
55 531 16.42 3.22 53 9.93
56 550 16.42 3.41 56 9.82
57 567 16.41 3.62 59 9.52
58 585 16.40 3.76 62 9.42
59 603 16.40 3.98 65 9.25
60 623 16.40 4.14 68 9.11
61 642 16.39 4.37 72 8.88
62 662 16.40 4.57 75 8.75
63 683 16.39 4.76 78 8.73
64 703 16.38 5.00 82 8.61
65 724 16.38 5.21 85 8.49
66 745 16.37 5.43 89 8.36
67 766 16.37 5.65 93 8.22
68 788 16.37 5.93 97 8.05
69 809 16.36 6.26 102 7.83
70 831 16.35 6.50 106 7.79
71 851 16.35 6.71 110 7.73
72 873 16.34 7.00 114 7.56
73 896 16.33 7.24 118 7.53
74 918 16.32 7.53 123 7.42
75 940 16.32 7.80 127 7.34
76 960 16.30 8.13 133 7.24
77 982 16.30 8.48 138 7.09
78 1003 16.30 8.82 144 7.00
79 1024 16.29 9.17 149 6.91
80 1047 16.28 9.52 155 6.77
81 1068 16.27 9.85 160 6.71
82 1090 16.26 10.20 166 6.61
83 1112 16.25 10.52 171 6.57
84 1133 16.25 10.91 177 6.44
85 1156 16.24 11.22 182 6.39
86 1179 16.24 11.63 189 6.30
87 1202 16.23 12.01 195 6.22
88 1223 16.22 12.37 201 6.16
89 1244 16.20 12.74 206 6.07
90 1268 16.19 13.07 212 6.03
91 1291 16.19 13.48 218 5.98
92 1313 16.18 13.90 225 5.89
93 1333 16.17 14.33 232 5.80
94 1357 16.17 14.76 239 5.72
95 1382 16.16 15.16 245 5.68
96 1406 16.14 15.60 252 5.62
97 1427 16.14 16.03 259 5.55
98 1448 16.12 16.54 267 5.46
99 1471 16.12 17.16 276 5.33
вывод:
соберете квадрик с полетным весом от 500 до 900 грамм (шутю), летать будете очень долго на такой ВМГ 😃
=================================================================================================
ЕЩЕ (теперь для 3 банок) обработанные данные со стенда (4 теста подряд, среднее значение):
мотор - SunnySky V3508-20 KV580
пропеллер - APC 12x8 Slo-flyer Propeller
аккумулятор - ZIPPY Compact 4000mAh 3S 25C (2 пака в параллель)
регулятор - SK-30A SimonK Firmware Multicopter Speed Controller ESC 30A
тяга
напряжение
ток
мощность
эффективность
% g v a w e
============================================
0 0 12.27 0.00 0.00 0.00
1 0 12.27 0.00 0.00 0.00
2 0 12.27 0.00 0.00 0.00
3 0 12.27 0.00 0.00 0.00
4 0 12.27 0.04 0.46 0.00
5 0 12.26 0.05 0.61 0.00
6 0 12.26 0.07 0.80 0.45
7 2 12.26 0.07 0.80 2.15
8 3 12.26 0.07 0.83 3.32
9 4 12.26 0.08 1.01 3.46
10 6 12.26 0.09 1.10 4.46
11 8 12.25 0.10 1.23 5.52
12 11 12.25 0.11 1.29 7.25
13 14 12.24 0.11 1.35 8.81
14 16 12.24 0.12 1.47 9.62
15 19 12.24 0.13 1.62 10.62
16 22 12.24 0.15 1.84 10.95
17 26 12.24 0.16 1.99 11.88
18 29 12.24 0.20 2.39 11.06
19 33 12.24 0.22 2.69 11.60
20 37 12.23 0.24 2.88 12.22
21 41 12.22 0.25 3.03 12.94
22 45 12.22 0.26 3.21 14.11
23 50 12.22 0.30 3.61 13.43
24 55 12.22 0.32 3.85 13.97
25 59 12.21 0.34 4.09 14.26
26 64 12.21 0.37 4.46 14.58
27 69 12.21 0.40 4.85 14.13
28 75 12.21 0.43 5.25 14.32
29 80 12.19 0.45 5.43 15.08
30 86 12.19 0.47 5.70 15.26
31 91 12.18 0.51 6.16 15.20
32 97 12.18 0.53 6.49 15.42
33 103 12.18 0.57 6.97 15.18
34 110 12.17 0.62 7.58 14.83
35 117 12.17 0.67 8.16 14.35
36 124 12.17 0.73 8.92 14.06
37 131 12.16 0.78 9.45 14.17
38 139 12.16 0.83 10.06 14.17
39 147 12.16 0.89 10.82 14.02
40 154 12.15 0.95 11.57 13.76
41 162 12.15 1.02 12.39 13.50
42 170 12.15 1.05 12.69 13.92
43 178 12.15 1.09 13.18 13.91
44 187 12.15 1.15 13.91 13.98
45 195 12.14 1.21 14.63 13.87
46 204 12.13 1.27 15.40 13.85
47 213 12.13 1.33 16.13 13.75
48 222 12.13 1.38 16.76 13.86
49 232 12.12 1.46 17.72 13.67
50 242 12.12 1.51 18.33 13.62
51 251 12.12 1.60 19.42 13.19
52 260 12.12 1.66 20.09 13.35
53 270 12.12 1.76 21.27 13.07
54 281 12.11 1.86 22.46 12.96
55 293 12.10 1.94 23.45 12.98
56 305 12.10 2.03 24.51 12.99
57 316 12.10 2.10 25.39 12.84
58 327 12.10 2.18 26.41 12.77
59 338 12.09 2.27 27.43 12.64
60 350 12.09 2.41 29.08 12.21
61 363 12.08 2.51 30.31 12.12
62 375 12.07 2.63 31.79 11.98
63 387 12.08 2.75 33.16 11.94
64 399 12.08 2.87 34.62 11.73
65 411 12.08 3.03 36.57 11.36
66 424 12.08 3.16 38.15 11.21
67 436 12.08 3.27 39.45 11.13
68 449 12.07 3.43 41.35 10.92
69 462 12.07 3.56 43.00 10.78
70 475 12.06 3.69 44.52 10.67
71 488 12.06 3.87 46.60 10.53
72 502 12.06 4.02 48.44 10.46
73 515 12.05 4.19 50.48 10.28
74 529 12.04 4.34 52.25 10.17
75 543 12.04 4.51 54.26 10.05
76 557 12.03 4.68 56.33 9.95
77 571 12.03 4.85 58.45 9.81
78 585 12.02 5.06 60.94 9.64
79 599 12.02 5.28 63.49 9.43
80 613 12.01 5.52 66.45 9.25
81 627 12.01 5.73 69.00 9.12
82 643 12.01 5.95 71.60 9.03
83 658 12.00 6.20 74.48 8.90
84 673 12.00 6.40 76.91 8.80
85 688 11.99 6.66 80.01 8.62
86 704 11.99 6.91 82.92 8.50
87 719 11.97 7.13 85.48 8.41
88 733 11.96 7.38 88.44 8.29
89 748 11.95 7.62 91.17 8.21
90 764 11.95 7.87 94.15 8.11
91 778 11.95 8.12 97.17 8.00
92 792 11.94 8.37 100.11 7.89
93 808 11.94 8.65 103.41 7.82
94 822 11.93 8.92 106.55 7.72
95 837 11.93 9.21 109.93 7.62
96 853 11.91 9.48 113.05 7.54
97 868 11.91 9.84 117.24 7.39
98 889 11.90 10.17 121.07 7.32
99 913 11.89 10.43 124.15 7.33
очередной скетч прошивки
#include <EEPROM2.h> //подключаем библиотеку EEPROM2
#include <Servo.h> // добавляем библиотеку для работы с сервоприводами
//объявление переменных
//подключаемые разьемы на ардуине
#define servoPin 3 // для дальнейшей работы назовем 3 пин как servoPin
int DATA = 4; //пин D4 подключаем АЦП тяги
int SCLK = 5; //пин D5 подключаем АЦП тяги
int PWDN = 6; //пин D6 подключаем АЦП тяги
#define CurrPin A0 //пин A0 датчик тока
#define VoltPin A1 //пин A1 датчик напряжения
#define servoMinImp 544 // 544 это стандартная длина импульса при котором сервопривод должен принять положение 0°
#define servoMaxImp 2400 // 2400 это эталонная длина импульса при котором сервопривод должен принять положение 180°
//переменные для работы
unsigned long volt; //четырех байтная переменная для хранения в памяти
unsigned long amper; //четырех байтная переменная для хранения в памяти
unsigned long gramm; //четырех байтная переменная для хранения в памяти
float grammT = 0;
int32_t grammM = 0;
float voltT = 0;
int32_t voltM = 0;
float amperT = 0;
int32_t amperM = 0;
int nullFilter = 0;
int CurrentValueOld = 0;
int CurrentValueNew = 0;
int VoltageValueOld = 0;
int VoltageValueNew = 0;
float CurrentValue = 0; //переменная для расчета тока (с плавающей точкой)
float CurrentValueRes = 0; //переменная с результатом для расчета тока (с плавающей точкой)
float VoltageValue = 0; //переменная для расчета напряжения (с плавающей точкой)
int32_t Weight = 0; //переменная для расчета тяги (32 разряда)
int val; //здесь будет храниться принятый символ
int n; //рабочая переменная
int error = 0; //так же рабочая переменная
int throttle = 0; //переменная газа
String strnumber = "0"; //переменная для временных текствых значаний
int throttleOld = 0; //переменная для хранения временных значений газа
//переменные для нулевых значений
int32_t WeightNull = 0; //нулевое значение по весу (переменная калибруется при включении)
int CountNull = 0; //нулевое значение по току, данная переменная для однонаправленных датчиков ACS758 (с буквой U) не используется (переменная калибруется при включении)
//эти переменные заполняются пользователем
int ISensor = 200; //максимальное значение измеряемое датчиком (смотрим даташит по ним)
Servo myServo;
//инициализация
void setup() {
//инициализация I/O
pinMode(DATA, INPUT);
pinMode(SCLK, OUTPUT);
pinMode(PWDN, OUTPUT);
digitalWrite(PWDN, HIGH);
Serial.begin(9600); //скорость порта
myServo.attach(servoPin, servoMinImp, servoMaxImp);
// устанавливаем пин как вывод управления сервоприводом,
// а также для работы сервопривода непосредственно в диапазоне углов от 0 до 180° задаем мин и макс значения импульсов.
// импульсы с большей или меньшей длиной восприниматься не будут.
// для сервоприводов даже одной партии значения длин импульсов могут отличаться, может быть даже и 584-2440.
// поэкспериментируйте и найдите идеальные длины импульсов конкретно для вашего сервопривода.
myServo.writeMicroseconds(set_pos(0)); //газ в ноль при включении
}
//чтение вводимой строки из терминала
//нахождение в цыкле пока не будет нажат ENTER или набранно определенное количество символов
//возвращает набранную строку
String readText(int n){
int i = 0; //временная целая переменная
String str; //временная строковая переменная
//собираем заданное количество символов
while (i<n) {
while (!(Serial.available())); //ждем символ
val = Serial.read(); //дождавшись, читаем его
if (val==13){return str;} //если нажат Enter, прекращаем ввод символов и передаем набранную строку
Serial.print(char(val)); //показываем нажатую клавишу на терминале
str += char(val); //формируем строку
i++; //наращиваем переменную
}
return str; //передаем набранную строку заданной длины
}
// Функция устанавливает стик газа
//диапазон желательно указывать от 0 до 100
int set_pos(int pos) {
int tmp=(servoMaxImp - servoMinImp) /100;
pos = servoMinImp + tmp * pos;
return pos;
}
//вывод меню для начала теста
//предоставление выбора типа проводимого теста
void beginTest(){
//вывод меню выбора
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - begin auto test 50, 65, 75, 85, 100%");
Serial.println("2 - begin auto test 1-100%");
Serial.println("3 - begin manual test");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//по результатам выбора начинаем тест или переходим в консоль
if (val==49){test(1);} //переход на тест с указанием номера теста 1
if (val==50){test(2);} //переход на тест с указанием номера теста 2
if (val==51){test(3);} //переход на тест с указанием номера теста 3
Serial.println("\n\r stop test return to console"); return; //возвращаем в консоль
}
//начало теста
//в зависимости от выбора, запускается тест ВМГ
int test(int n){
//ждем нажатие подтверждения начала тестов
Serial.println("\n\r============= Select action: =============");
Serial.println("8 - begin test");
Serial.println("any key - stop test and return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//если подтверждение нажато, начинаем тест, иначе выходим в консоль
if (val==56){
Serial.println("\n\r start test"); Serial.println(); //информируем о начале теста
//первый тест
if (n==1){
Serial.println("set throttle 50% 65% 75% 85% 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); //формируем шапку для вывода результатов
setthrottle(50, 1, 0); if (delayM(1000)==1){return 0;} printRez(50); //газ плавно доводим до 50%, ждем, выводим результат
setthrottle(65, 1, 0); if (delayM(1000)==1){return 0;} printRez(65); //газ плавно доводим до 65%, ждем, выводим результат
setthrottle(75, 1, 0); if (delayM(1000)==1){return 0;} printRez(75); //газ плавно доводим до 75%, ждем, выводим результат
setthrottle(85, 1, 0); if (delayM(1000)==1){return 0;} printRez(85); //газ плавно доводим до 85%, ждем, выводим результат
setthrottle(100, 1, 0); if (delayM(1000)==1){return 0;} printRez(100); //газ плавно доводим до 100%, ждем, выводим результат
setthrottle(0, 0, 1); //газ в ноль
}
//второй тест
if (n==2){
Serial.println("throttle from 0 to 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); //формируем шапку для вывода результатов
nullFilter=0; for (n=0; n<100; n++){myServo.writeMicroseconds(set_pos(n)); printRez(n); if (delayM(50)==1){return 0;};} //плавный набот газа от 0% до 100% с выводом результата и возможностью прерывания процесса тестирования
Serial.println("throttle = 0%"); myServo.writeMicroseconds(set_pos(0)); //заканчиваем тест, газ в 0%
}
//третий тест
if (n==3){
Serial.println("select throttle percent or press +/- or r for print result"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//если нажат + (причем любой) наращиваем значение газа, так же присутствует вывод степени набора газа, ограничение на больше 100% и прерывание процесса тестирования
if (val==61 || val==43){if (error==1){breakTest(); return 0;}else if (throttle<=99){throttle++; setthrottle(throttle, 0, 1);}else{Serial.println("maximal throttle 100%");}}
//подобно условию выше для знака +, только теперь для знака -
else if (val==45){if (error==1){breakTest(); return 0;}else if (throttle>=1){throttle--; setthrottle(throttle, 0, 1);}else{Serial.println("minimal throttle 0%");}}
//при нажатии Enter, формируется и устанавливается уровень газа с выводом уровня установленного газа
else if (val==13){Serial.println(); error=0; throttle=strnumber.toInt(); if (throttle>=101){breakTest(); return 0;} setthrottle(throttle, 1, 1); strnumber="0";}
//тут мы формируем уровень газа путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//если в процессе работы теста нажать калвишу "r", то произойдет вывод данных датчиков
else if (val==114){Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); printRez(throttle);}
//завершаем тест
else {breakTest(); return 0;}
}
}
}
return 0; //если нажата не "8", завершаем тест
}
//установка уровня газа
//при нулевом значении газ обрабатывается моментально, использовать только для снижения значения
//при занчении противоположном нулевому, газ будет набираться плавно
//еще добавлено одно значение для разрешения/запрета вывода результата установленного уровня газа
void setthrottle(int throttle, int x, int y){
int r = 0; //обнуляем переменную
//если значение переменной х равно 0, изменение газа происходит моментально, при любом другом, газ будет наращиваться плавно
if (x==0){
myServo.writeMicroseconds(set_pos(throttle)); //моментальное изменение газа
}else if (throttleOld>=throttle){myServo.writeMicroseconds(set_pos(throttle)); //условие для активации плавного набора газа
}else{
r = throttle - throttleOld; //просчитываем разность старого и нового значения газа для счетчика
//плавное изменение газа
for (n=0; n<r; n++){
myServo.writeMicroseconds(set_pos(throttleOld+n)); //изменяем уровень газа
if (delayM(30)==1){return;} //задержка и возможность прекращение теста по нажатию на клавишу
}
}
if (y==1){Serial.print("throttle = "); Serial.print(throttle); Serial.println("%");} //еслт y имеет значение 1, выводим результаты значения газа
throttleOld=throttle; //формируем старые показания уровня газа
return; //выход из подпрограммы
}
//функция прерывания теста, выводим сообщение о прерывании, ставим значение уровня газа в 0, обнуляем переменные
void breakTest(){
Serial.println("throttle = 0%");
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r break");
throttle=0; strnumber="0"; throttleOld=0;
return;
}
//функция задержки с возможностью прерывания
int delayM(int m){
int k;
for (k=0; k<m; k++){
if (!(Serial.available())){}else{k = 1; breakTest(); return k;}
delay(1);
}
k = 0;
return k;
}
//функция калибровки для уровня газа (еще не готова)
void servaC(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - 100%");
Serial.println("0 - 0%");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (1){
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){
myServo.writeMicroseconds(set_pos(100));
myServo.attach(servoPin, servoMinImp, servoMaxImp);
Serial.println("\n\r 100% ok");
}
if (val==48){
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r 0% ok");
}
if (val==49 || val==48){}else{return;}
}
}
//формирование меню калибровок
void beginCalibrate(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - calibration weight");
Serial.println("2 - calibration voltage");
Serial.println("3 - calibration curent");
Serial.println("4 - calibration ESC");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){weightC();}
if (val==50){voltC();}
if (val==51){amperC();}
if (val==52){servaC();}
Serial.println("\n\r stop calibration return to console");
return;
}
void weightC(){
Serial.println("put standard and set weight"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//при нажатии Enter
if (val==13){Serial.println(); error=0; grammT=strnumber.toInt(); strnumber="0"; grammM=((getSensorValueWeight() - WeightNull)/grammT)*1000000; EEPROM_write(15, grammM); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {return;}
}
}
void voltC(){
Serial.println("connect standard and set real volt"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//при нажатии Enter
if (val==13){Serial.println(); error=0; voltT=strnumber.toInt(); strnumber="0"; voltM=voltT/analogRead(VoltPin)/100*1000000; EEPROM_write(0, voltM); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {return;}
}
}
void amperC(){
Serial.println("connect standard and set real current"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//если нажат + (причем любой) наращиваем значение газа, так же присутствует вывод степени набора газа, ограничение на больше 100% и прерывание процесса тестирования
if (val==61 || val==43){if (error==1){breakTest(); return;}else if (throttle<=99){throttle++; setthrottle(throttle, 0, 1);}else{Serial.println("maximal throttle 100%");}}
//подобно условию выше для знака +, только теперь для знака -
else if (val==45){if (error==1){breakTest(); return;}else if (throttle>=1){throttle--; setthrottle(throttle, 0, 1);}else{Serial.println("minimal throttle 0%");}}
//при нажатии Enter
else if (val==13){Serial.println(); error=0; amperT=strnumber.toInt(); strnumber="0"; amperM=amperT/(analogRead(CurrPin)-CountNull)/100*1000000; EEPROM_write(7, amperM); breakTest(); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {breakTest(); return;}
}
}
//чтение данных тяги
int32_t getSensorValueWeight() {
digitalWrite(SCLK, LOW); // wake up ADC
while (digitalRead(DATA) == HIGH); // wait for data ready, stay in while-loop until LOW
Weight = shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
digitalWrite(SCLK, HIGH); // enter sleep mode
Weight = ((signed long) (Weight << 8)) >> 8; // process as int24_t (two's compliment 24bit)
return Weight;
}
//результат по тяге
int weightRez(){
Weight = (getSensorValueWeight() - WeightNull)/grammT;;
return Weight;
}
//результат по напряжению
float voltageRez(){
//расчет данных напряжения
VoltageValue = analogRead(VoltPin); // считываем значение аналогового входа (напряжение)
//if (nullFilter==0){VoltageValueOld=VoltageValueNew;}; VoltageValueOld=VoltageValue=filter(VoltageValueOld, VoltageValueNew);
VoltageValue = VoltageValue*voltT; ;
return VoltageValue;
}
//результат по току
float currentRez(){
//расчет данных тока
CurrentValue = analogRead(CurrPin); (CurrentValueNew); // считываем значение аналогового входа (ток)
//if (nullFilter==0){CurrentValueOld=CurrentValueNew;}; CurrentValueOld=CurrentValue=filter(CurrentValueOld, CurrentValueNew); // Serial.println(CurrentValue);
CurrentValueRes = (CurrentValue-CountNull)*amperT;
//CurrentValueRes = (CurrentValue-CountNull)*ISensor/512; //формула расчета тока для двунаправленнх датчиков ACS758
//CurrentValueRes = CurrentValue*ISensor/1024; //формула расчета тока для однонаправленных датчиков ACS758
return CurrentValueRes;
}
//выводим результаты датчиков, переменная v для уровня газа
void printRez(int v){
//if (visable==0){voltageRez(); currentRez(); return;}
//выводим результат
Serial.print(v);
Serial.print("\t");
Serial.print(weightRez());
Serial.print("\t");
VoltageValueNew=100*voltageRez();
Serial.print((float)VoltageValueNew/100);
Serial.print("\t");
if (nullFilter==0){VoltageValueOld=VoltageValueNew;};
VoltageValueNew=filter(VoltageValueOld, VoltageValueNew);
VoltageValue=(float)VoltageValueNew/100;
(VoltageValue);
("\t");
VoltageValue=VoltageValue*(1-(float)v/10000);
Serial.print(VoltageValue);
VoltageValueOld=VoltageValueNew;
Serial.print("\t");
CurrentValueNew=100*currentRez();
Serial.print((float)CurrentValueNew/100);
Serial.print("\t");
if (nullFilter==0){CurrentValueOld=CurrentValueNew;};
CurrentValueNew=filter(CurrentValueOld, CurrentValueNew);
CurrentValueRes=(float)filter(CurrentValueOld, CurrentValueNew)/100;
(CurrentValueRes);
("\t");
CurrentValueRes=CurrentValueRes*1.5;
Serial.println(CurrentValueRes);
CurrentValueOld=CurrentValueNew;
Serial.flush();
nullFilter=1;
}
void nullF(){
//вывод меню выбора
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - null weight");
Serial.println("2 - null current");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//по результатам выбора обнуляем датчики
if (val==49){WeightNull = getSensorValueWeight(); EEPROM_write(23, WeightNull); Serial.println("\n\r zero value of the set");} //обнуляем датчик веса
if (val==50){CountNull = analogRead(CurrPin); EEPROM_write(31, CountNull); Serial.println("\n\r zero value of the set");} //обнуляем датчик тока
Serial.println("\n\r return to console"); return; //возвращаем в консоль
}
//фильтр
int filter(int y, int r)
{
int z = (15 * y + r) >> 4;
return z;
}
//начало программы
void loop()
{
EEPROM_read(0, volt); //читаем из пямяти переменную
EEPROM_read(7, amper); //читаем из пямяти переменную
EEPROM_read(15, gramm); //читаем из пямяти переменную
voltT = (float)volt/1000000;
amperT = (float)amper/1000000; (amper);
grammT = (float)gramm/1000000;
EEPROM_read(23, WeightNull);
EEPROM_read(31, CountNull);
Serial.println();
Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); nullFilter=0; printRez(0);
Serial.println();
("Helow my friend!");
Serial.println("Please type the comands:");
Serial.println("test, calibration, null");
Serial.println();
Serial.print(">");
while (!(Serial.available()));
String myString = readText(60);
if (myString=="test" || myString=="t"){Serial.println(); beginTest(); error = 0;}
//if (myString=="setup"){Serial.println("\n\r setup ok"); error = 0;}
if (myString=="calibration" || myString=="c"){Serial.println(); beginCalibrate(); error = 0;}
if (myString=="null" || myString=="n"){nullF(); error = 0;}
if (myString==""){Serial.println(); error = 0;}
if (error==0){error=1;}else{Serial.println("\n\r incorrect command");}
}
разнес калибровку для тяги и тока по отдельности, ток калибрануть можно единожды, а вот тягу следует калибровать в зависимости от температуры воздуха
пока верно работает тест номер два, остальные допилю попозжа
Инструкция
Будьте внимательны при работе со стендом!!!
DOS-интерфейс
Имея скромные познания в программировании, и тем более работая над проектом, впервые столкнулся с платформой ардуина (имеется в виду, что либо писать под нее), решил не слишком напрягаться и создать интерфейс а ля DOS-консоль (так как хотелось побыстрее получить результаты).
И так, слепленный из чего под руку попавшееся наш стенд, подключаем к юзби компьютера, запускаем любой терминал (PuTTY, ардуиновский, маздаевский Hiper Terminal и т. д.).
Начальное меню будет выглядеть так:
% g v v+f+* a a+f+*
0 0 0.00 0.00 0.00 0.00
Please type the commands:
test(t), calibration(c), null(n)
>
Первым делом вам предлагаются данные с датчиков.
% - шаг тяги
g - тяга (не нуждается в фильтрации ИМХО)
v - напряжение как есть
v+f+* - напряжение после фильтра и коэффициента для выравнивания
a - ток как есть
a+f+* - ток после фильтра и коэффициента для выравнивания
Данные “как есть” предназначены для ваших фильтров, если надумаете писать свои обработчики данных или интерфейсы.
Нажмите Enter и данные с датчиков прочитаются еще раз.
Таким образом можно мониторить данные с датчиков.
Дальше имеем подсказку, что можно выбрать для последующих действий.
test(t) - перейти в меню тестов
calibration© - перейти в меню калибровки датчиков
null(n) - перейти в меню установки нулевых значений
Первым делом нам следует установить нулевое значение и откалибровать датчики.
Нажимаем клавишу “n” - переходим в меню установки нулевых значений.
============= Select action: =============
1 - null weight
2 - null current
any key - return to console
==========================================
1 - обнуление датчика тяги
2 - обнуление датчика тока
любая клавиша - возврат в начальное меню
Уберите с датчика тяги любой посторонний вес и нажмите клавишу “1”, произойдет обнуление значения данных с тензадатчика. Под посторонним весом подразумевается все, что вносит погрешность в измерение. У меня в тензодатчик вкручен болт, с помощью его я регулирую расстояние до ноги луча, но меняя разные пропеллеры, которые имеют разный вес, не обязательно болтом подгонять идеальное расстояние, достаточно просто принять малую долю в изменении веса за нулевое значение. Так же обнуление датчика тяги может понадобиться при длительной эксплуатации или изменении температуры.
Также следует обнулить начальные значения с датчика тока. Для этого отключите любую нагрузку (регулятор) и нажмите клавишу “2”, предварительно войдя в меню обнуления. Это следует проделать единожды и повторять, если заметите изменение нулевого значения.
Установив нулевые значения для датчиков, откалибруем теперь их.
Вызываем меню калибровок клавишей “с”
============= Select action: =============
1 - calibration weight
2 - calibration voltage
3 - calibration current
4 - calibration ESC
any key - return to console
==========================================
1 - калибровка тяги
2 - калибровка напряжения
3 - калибровка тока
4 - калибровка регуля
любая клавиша - выход в начальное меню
Для калибровки тяги нажимаем клавишу “1”. Берем эталонный вес, его можно получить разными способами, например, если нет весов в наличии, возьмите любой предмет и взвесьте его на магазинных весах, на крайний случай при покупке продуктов на них указывается вес. В общем, чем точнее будет значение веса эталона, тем лучше для получаемых результатов. Кладем эталон на тензодатчик и набираем вес в граммах, после чего нажимаем “Enter”. Проверяем точность.
Для калибровки напряжения нажмите клавишу “2” из меню калибровок и так же как в предыдущем абзаце введите значение эталонного напряжения, предварительно подключив аккумулятор к стенду и измерив напряжение тестером. Ввод напряжения производится без учета запятой. Например напряжение 4 баночного аккумулятора значением в 16,65 вольта следует ввести как 1665 и нажать клавишу “Enter”.
Калибровка датчика тока. Как и следовало ожидать, из меню калибровок нажимаем клавишу “3” и так же вводим значение тока без запятой с эталонного замера. Здесь имеются некоторые сложности в получении эталонного значения по току. Если вы имеете какие либо предложения для решения данной проблемы, прошу высказываться. Пока более простого решения нет, в программе все таки имеется возможность калибровки. Для этого в разрыв питания регуля подключаем амперметр. Собираем ВМГ как для теста и нагружаем датчик тока путем раскрутки ВМГ. В режиме ввода эталонного значения тока можно нажимать клавиши “+” и “-” для задействования ВМГ в качестве нагрузки. Плюсом будем увеличивать обороты, минусом уменьшать. Но не забываем перед этими действиями откалибровать регулятор.
ВНИМАНИЕ!!! СНИМИТЕ ПРОПЕЛЛЕР С МОТОРА.
Калибровка регулятора (установка высокого и низкого уровня). Сигнальный провод регулятора должен быть отключен от стенда. Выбираем данный режим нажав клавишу “4”.
==========================================
1 - 100%
0 - 0%
any key - return to console
==========================================
Клавишей “1” вы установите высокий уровень на клейме стенда, подключите сигнальный разъем от регуля к стенду, регуль (сигналы могут быть разными) пропищит, нажмите клавишу “2”, установится нулевое значение на клейме стенда, после этого регуль готов для работы. Проверяем уровни например ручным тестом. Вращаться мотор должен начать при уровне 0-5% и максимально вращаться на 95-100%.
Закончив обнуление и калибровку стенда можно приступать к работе.
Имеется три режима тестов.
Нажмите клавишу “t”
============= Select action: =============
1 - begin auto test 50, 65, 75, 85, 100%
2 - begin auto test 1-100%
3 - begin manual test
any key - return to console
==========================================
1 - запускаем тест с замером промежутков по тяге 50, 65, 75, 85, 100%
2 - запускаем тест с шагом тяги от 1 до 100%
3 - запускаем тест с ручным управлением тяги
любая клавиша - выйти в основное меню
Первый и второй тесты стандартно на автомате крутанут ВМГ и выдадут результат.
Третий тест нажимая клавишу “+” и “-” устанавливаем тягу в пределах от 1 до 100%, так же можно ввести значение тяги цифровыми клавишами и нажать “Enter”, тяга постепенно, что бы рывком не нагрузить ВМГ, наберет требуемый шаг тяги или резко его сбросит до требуемого значения. Клавишей “r” вы получите результаты с датчиков. Любая не задействованная клавиша остановит тест и вернет вас в начальное меню.
На этом описание работы со стендом думаю будет достаточным.
Дальше будет расписано как быстро и просто обработать данные полученные со стенда.
Скетч последних изменений
#include <EEPROM2.h> //подключаем библиотеку EEPROM2
#include <Servo.h> // добавляем библиотеку для работы с сервоприводами
//объявление переменных
//подключаемые разьемы на ардуине
#define servoPin 3 // для дальнейшей работы назовем 3 пин как servoPin
int DATA = 4; //пин D4 подключаем АЦП тяги
int SCLK = 5; //пин D5 подключаем АЦП тяги
int PWDN = 6; //пин D6 подключаем АЦП тяги
#define CurrPin A0 //пин A0 датчик тока
#define VoltPin A1 //пин A1 датчик напряжения
#define servoMinImp 544 // 544 это стандартная длина импульса при котором сервопривод должен принять положение 0°
#define servoMaxImp 2400 // 2400 это эталонная длина импульса при котором сервопривод должен принять положение 180°
//переменные для работы
unsigned long volt; //четырех байтная переменная для хранения в памяти
unsigned long amper; //четырех байтная переменная для хранения в памяти
unsigned long gramm; //четырех байтная переменная для хранения в памяти
float grammT = 0;
int32_t grammM = 0;
float voltT = 0;
int32_t voltM = 0;
float amperT = 0;
int32_t amperM = 0;
int nullFilter = 0;
int CurrentValueOld = 0;
int CurrentValueNew = 0;
int VoltageValueOld = 0;
int VoltageValueNew = 0;
float CurrentValue = 0; //переменная для расчета тока (с плавающей точкой)
float CurrentValueRes = 0; //переменная с результатом для расчета тока (с плавающей точкой)
float VoltageValue = 0; //переменная для расчета напряжения (с плавающей точкой)
int32_t Weight = 0; //переменная для расчета тяги (32 разряда)
int val; //здесь будет храниться принятый символ
int n; //рабочая переменная
int error = 0; //так же рабочая переменная
int throttle = 0; //переменная газа
String strnumber = "0"; //переменная для временных текствых значаний
int throttleOld = 0; //переменная для хранения временных значений газа
//переменные для нулевых значений
int32_t WeightNull = 0; //нулевое значение по весу (переменная калибруется при включении)
int CountNull = 0; //нулевое значение по току, данная переменная для однонаправленных датчиков ACS758 (с буквой U) не используется (переменная калибруется при включении)
//эти переменные заполняются пользователем
int ISensor = 200; //максимальное значение измеряемое датчиком (смотрим даташит по ним)
Servo myServo;
//инициализация
void setup() {
//инициализация I/O
pinMode(DATA, INPUT);
pinMode(SCLK, OUTPUT);
pinMode(PWDN, OUTPUT);
digitalWrite(PWDN, HIGH);
Serial.begin(9600); //скорость порта
myServo.attach(servoPin, servoMinImp, servoMaxImp);
// устанавливаем пин как вывод управления сервоприводом,
// а также для работы сервопривода непосредственно в диапазоне углов от 0 до 180° задаем мин и макс значения импульсов.
// импульсы с большей или меньшей длиной восприниматься не будут.
// для сервоприводов даже одной партии значения длин импульсов могут отличаться, может быть даже и 584-2440.
// поэкспериментируйте и найдите идеальные длины импульсов конкретно для вашего сервопривода.
myServo.writeMicroseconds(set_pos(0)); //газ в ноль при включении
}
//чтение вводимой строки из терминала
//нахождение в цыкле пока не будет нажат ENTER или набранно определенное количество символов
//возвращает набранную строку
String readText(int n){
int i = 0; //временная целая переменная
String str; //временная строковая переменная
//собираем заданное количество символов
while (i<n) {
while (!(Serial.available())); //ждем символ
val = Serial.read(); //дождавшись, читаем его
if (val==13){return str;} //если нажат Enter, прекращаем ввод символов и передаем набранную строку
Serial.print(char(val)); //показываем нажатую клавишу на терминале
str += char(val); //формируем строку
i++; //наращиваем переменную
}
return str; //передаем набранную строку заданной длины
}
// Функция устанавливает стик газа
//диапазон желательно указывать от 0 до 100
int set_pos(int pos) {
int tmp=(servoMaxImp - servoMinImp) /100;
pos = servoMinImp + tmp * pos;
return pos;
}
//вывод меню для начала теста
//предоставление выбора типа проводимого теста
void beginTest(){
//вывод меню выбора
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - begin auto test 50, 65, 75, 85, 100%");
Serial.println("2 - begin auto test 1-100%");
Serial.println("3 - begin manual test");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//по результатам выбора начинаем тест или переходим в консоль
if (val==49){test(1);} //переход на тест с указанием номера теста 1
if (val==50){test(2);} //переход на тест с указанием номера теста 2
if (val==51){test(3);} //переход на тест с указанием номера теста 3
Serial.println("\n\r stop test return to console"); return; //возвращаем в консоль
}
//начало теста
//в зависимости от выбора, запускается тест ВМГ
int test(int n){
//ждем нажатие подтверждения начала тестов
Serial.println("\n\r============= Select action: =============");
Serial.println("8 - begin test");
Serial.println("any key - stop test and return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//если подтверждение нажато, начинаем тест, иначе выходим в консоль
if (val==56){
Serial.println("\n\r start test"); Serial.println(); //информируем о начале теста
//первый тест
if (n==1){
Serial.println("set throttle 50% 65% 75% 85% 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); //формируем шапку для вывода результатов
setthrottle(50, 1, 0); if (delayM(1000)==1){return 0;} nullFilter=0; printRez(50); //газ плавно доводим до 50%, ждем, выводим результат
setthrottle(65, 1, 0); if (delayM(1000)==1){return 0;} nullFilter=0; printRez(65); //газ плавно доводим до 65%, ждем, выводим результат
setthrottle(75, 1, 0); if (delayM(1000)==1){return 0;} nullFilter=0; printRez(75); //газ плавно доводим до 75%, ждем, выводим результат
setthrottle(85, 1, 0); if (delayM(1000)==1){return 0;} nullFilter=0; printRez(85); //газ плавно доводим до 85%, ждем, выводим результат
setthrottle(100, 1, 0); if (delayM(1000)==1){return 0;} nullFilter=0; printRez(100); //газ плавно доводим до 100%, ждем, выводим результат
setthrottle(0, 0, 1); //газ в ноль
}
//второй тест
if (n==2){
Serial.println("throttle from 0 to 100%"); //выводим сообщение
if (delayM(200)==1){return 0;} //пауза с возможностью прерывания по нажатию любой клавиши
Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); //формируем шапку для вывода результатов
nullFilter=0; for (n=0; n<100; n++){myServo.writeMicroseconds(set_pos(n)); printRez(n); if (delayM(50)==1){return 0;};} //плавный набот газа от 0% до 100% с выводом результата и возможностью прерывания процесса тестирования
Serial.println("throttle = 0%"); myServo.writeMicroseconds(set_pos(0)); //заканчиваем тест, газ в 0%
}
//третий тест
if (n==3){
Serial.println("select throttle percent or press +/- or r for print result"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//если нажат + (причем любой) наращиваем значение газа, так же присутствует вывод степени набора газа, ограничение на больше 100% и прерывание процесса тестирования
if (val==61 || val==43){if (error==1){breakTest(); return 0;}else if (throttle<=99){throttle++; setthrottle(throttle, 0, 1);}else{Serial.println("maximal throttle 100%");}}
//подобно условию выше для знака +, только теперь для знака -
else if (val==45){if (error==1){breakTest(); return 0;}else if (throttle>=1){throttle--; setthrottle(throttle, 0, 1);}else{Serial.println("minimal throttle 0%");}}
//при нажатии Enter, формируется и устанавливается уровень газа с выводом уровня установленного газа
else if (val==13){Serial.println(); error=0; throttle=strnumber.toInt(); if (throttle>=101){breakTest(); return 0;} setthrottle(throttle, 1, 1); strnumber="0";}
//тут мы формируем уровень газа путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//если в процессе работы теста нажать калвишу "r", то произойдет вывод данных датчиков
else if (val==114){Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); nullFilter=0; printRez(throttle);}
//завершаем тест
else {breakTest(); return 0;}
}
}
}
return 0; //если нажата не "8", завершаем тест
}
//установка уровня газа
//при нулевом значении газ обрабатывается моментально, использовать только для снижения значения
//при занчении противоположном нулевому, газ будет набираться плавно
//еще добавлено одно значение для разрешения/запрета вывода результата установленного уровня газа
void setthrottle(int throttle, int x, int y){
int r = 0; //обнуляем переменную
//если значение переменной х равно 0, изменение газа происходит моментально, при любом другом, газ будет наращиваться плавно
if (x==0){
myServo.writeMicroseconds(set_pos(throttle)); //моментальное изменение газа
}else if (throttleOld>=throttle){myServo.writeMicroseconds(set_pos(throttle)); //условие для активации плавного набора газа
}else{
r = throttle - throttleOld; //просчитываем разность старого и нового значения газа для счетчика
//плавное изменение газа
for (n=0; n<r; n++){
myServo.writeMicroseconds(set_pos(throttleOld+n)); //изменяем уровень газа
if (delayM(30)==1){return;} //задержка и возможность прекращение теста по нажатию на клавишу
}
}
if (y==1){Serial.print("throttle = "); Serial.print(throttle); Serial.println("%");} //еслт y имеет значение 1, выводим результаты значения газа
throttleOld=throttle; //формируем старые показания уровня газа
return; //выход из подпрограммы
}
//функция прерывания теста, выводим сообщение о прерывании, ставим значение уровня газа в 0, обнуляем переменные
void breakTest(){
Serial.println("throttle = 0%");
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r break");
throttle=0; strnumber="0"; throttleOld=0;
return;
}
//функция задержки с возможностью прерывания
int delayM(int m){
int k;
for (k=0; k<m; k++){
if (!(Serial.available())){}else{k = 1; breakTest(); return k;}
delay(1);
}
k = 0;
return k;
}
//функция калибровки для уровня газа (еще не готова)
void servaC(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - 100%");
Serial.println("0 - 0%");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (1){
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){
myServo.writeMicroseconds(set_pos(100));
myServo.attach(servoPin, servoMinImp, servoMaxImp);
Serial.println("\n\r 100% ok");
}
if (val==48){
myServo.writeMicroseconds(set_pos(0));
Serial.println("\n\r 0% ok");
}
if (val==49 || val==48){}else{return;}
}
}
//формирование меню калибровок
void beginCalibrate(){
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - calibration weight");
Serial.println("2 - calibration voltage");
Serial.println("3 - calibration current");
Serial.println("4 - calibration ESC");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read();
Serial.print("you select "); Serial.println(char(val));
if (val==49){weightC();}
if (val==50){voltC();}
if (val==51){amperC();}
if (val==52){servaC();}
Serial.println("\n\r stop calibration return to console");
return;
}
void weightC(){
Serial.println("put standard and set weight"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//при нажатии Enter
if (val==13){Serial.println(); error=0; grammT=strnumber.toInt(); strnumber="0"; grammM=((getSensorValueWeight() - WeightNull)/grammT)*1000000; EEPROM_write(15, grammM); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {return;}
}
}
void voltC(){
Serial.println("connect standard and set real volt"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//при нажатии Enter
if (val==13){Serial.println(); error=0; voltT=strnumber.toInt(); strnumber="0"; voltM=voltT/analogRead(VoltPin)/100*1000000; EEPROM_write(0, voltM); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {return;}
}
}
void amperC(){
Serial.println("connect standard and set real current"); //выводим сообщение
error=0; //обнуляем временную переменную
//создаем петлю
while (1){
while (!(Serial.available())); val = Serial.read(); //ждем нажатия клавиши и читаем ее
//если нажат + (причем любой) наращиваем значение газа, так же присутствует вывод степени набора газа, ограничение на больше 100% и прерывание процесса тестирования
if (val==61 || val==43){if (error==1){breakTest(); return;}else if (throttle<=99){throttle++; setthrottle(throttle, 0, 1);}else{Serial.println("maximal throttle 100%");}}
//подобно условию выше для знака +, только теперь для знака -
else if (val==45){if (error==1){breakTest(); return;}else if (throttle>=1){throttle--; setthrottle(throttle, 0, 1);}else{Serial.println("minimal throttle 0%");}}
//при нажатии Enter
else if (val==13){Serial.println(); error=0; amperT=strnumber.toInt(); strnumber="0"; amperM=amperT/(analogRead(CurrPin)-CountNull)/100*1000000; EEPROM_write(7, amperM); breakTest(); return;}
//тут мы формируем вес путем нажатия цифровых клавиш, формирование прекращается по нажатию клавиши Enter
else if (val>=48 && val<=57){Serial.print(char(val)); error=1; strnumber += char(val);}
//завершаем тест
else {breakTest(); return;}
}
}
//чтение данных тяги
int32_t getSensorValueWeight() {
digitalWrite(SCLK, LOW); // wake up ADC
while (digitalRead(DATA) == HIGH); // wait for data ready, stay in while-loop until LOW
Weight = shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
Weight <<= 8;
Weight |= shiftIn(DATA, SCLK, MSBFIRST);
digitalWrite(SCLK, HIGH); // enter sleep mode
Weight = ((signed long) (Weight << 8)) >> 8; // process as int24_t (two's compliment 24bit)
return Weight;
}
//результат по тяге
int weightRez(){
Weight = (getSensorValueWeight() - WeightNull)/grammT;;
return Weight;
}
//результат по напряжению
float voltageRez(){
//расчет данных напряжения
VoltageValue = analogRead(VoltPin); // считываем значение аналогового входа (напряжение)
//if (nullFilter==0){VoltageValueOld=VoltageValueNew;}; VoltageValueOld=VoltageValue=filter(VoltageValueOld, VoltageValueNew);
VoltageValue = VoltageValue*voltT; ;
return VoltageValue;
}
//результат по току
float currentRez(){
//расчет данных тока
CurrentValue = analogRead(CurrPin); (CurrentValueNew); // считываем значение аналогового входа (ток)
//if (nullFilter==0){CurrentValueOld=CurrentValueNew;}; CurrentValueOld=CurrentValue=filter(CurrentValueOld, CurrentValueNew); // Serial.println(CurrentValue);
CurrentValueRes = (CurrentValue-CountNull)*amperT;
//CurrentValueRes = (CurrentValue-CountNull)*ISensor/512; //формула расчета тока для двунаправленнх датчиков ACS758
//CurrentValueRes = CurrentValue*ISensor/1024; //формула расчета тока для однонаправленных датчиков ACS758
return CurrentValueRes;
}
//выводим результаты датчиков, переменная v для уровня газа
void printRez(int v){
//if (visable==0){voltageRez(); currentRez(); return;}
//выводим результат
Serial.print(v);
Serial.print("\t");
Serial.print(weightRez());
Serial.print("\t");
VoltageValueNew=100*voltageRez();
Serial.print((float)VoltageValueNew/100);
Serial.print("\t");
if (nullFilter==0){VoltageValueOld=VoltageValueNew;};
VoltageValueNew=filter(VoltageValueOld, VoltageValueNew);
VoltageValue=(float)VoltageValueNew/100;
(VoltageValue);
("\t");
VoltageValue=VoltageValue*(1-(float)v/10000);
Serial.print(VoltageValue);
VoltageValueOld=VoltageValueNew;
Serial.print("\t");
CurrentValueNew=100*currentRez();
Serial.print((float)CurrentValueNew/100);
Serial.print("\t");
if (nullFilter==0){CurrentValueOld=CurrentValueNew;};
CurrentValueNew=filter(CurrentValueOld, CurrentValueNew);
CurrentValueRes=(float)filter(CurrentValueOld, CurrentValueNew)/100;
(CurrentValueRes);
("\t");
CurrentValueRes=CurrentValueRes*1.5;
Serial.println(CurrentValueRes);
CurrentValueOld=CurrentValueNew;
Serial.flush();
nullFilter=1;
}
void nullF(){
//вывод меню выбора
Serial.println("\n\r============= Select action: =============");
Serial.println("1 - null weight");
Serial.println("2 - null current");
Serial.println("any key - return to console");
Serial.println("==========================================");
while (!(Serial.available())); val = Serial.read(); //ожидание выбора
Serial.print("you select "); Serial.println(char(val)); //сообщаем, что выбрали
//по результатам выбора обнуляем датчики
if (val==49){WeightNull = getSensorValueWeight(); EEPROM_write(23, WeightNull); Serial.println("\n\r zero value of the set");} //обнуляем датчик веса
if (val==50){CountNull = analogRead(CurrPin); EEPROM_write(31, CountNull); Serial.println("\n\r zero value of the set");} //обнуляем датчик тока
Serial.println("\n\r return to console"); return; //возвращаем в консоль
}
//фильтр
int filter(int y, int r)
{
int z = (15 * y + r) >> 4;
return z;
}
//начало программы
void loop()
{
EEPROM_read(0, volt); //читаем из пямяти переменную
EEPROM_read(7, amper); //читаем из пямяти переменную
EEPROM_read(15, gramm); //читаем из пямяти переменную
voltT = (float)volt/1000000;
amperT = (float)amper/1000000; (amper);
grammT = (float)gramm/1000000;
EEPROM_read(23, WeightNull);
EEPROM_read(31, CountNull);
Serial.println();
Serial.println("\n\r%\tg\tv\tv+f+*\ta\ta+f+*"); nullFilter=0; printRez(0);
Serial.println();
("Hellow my friend!");
Serial.println("Please type the commands:");
Serial.println("test(t), calibration(c), null(n)");
Serial.println();
Serial.print(">");
while (!(Serial.available())); val = Serial.read(); Serial.print("you select "); Serial.println(char(val));
//String myString = readText(60);
if (val==116){Serial.println(); beginTest(); error = 0;}
//if (myString=="setup" || myString=="s"){Serial.println("\n\r setup ok"); error = 0;}
if (val==99){Serial.println(); beginCalibrate(); error = 0;}
if (val==110){nullF(); error = 0;}
if (val==13){Serial.println(); error = 0;}
if (error==0){error=1;}else{Serial.println("\n\r incorrect command");}
}
Как быстро обработать данные полученные со стенда и предоставить их в удобочитаемом виде?
Я пользуюсь терминалом PuTTY. Запускаем тест под номером 2 (плавное измерение с шагом тяги от 0 до 100%) четыре раза подряд.
Верхний левый угол путти выбираем скопировать все данные в клипбоард. Дальше вставляю их в Notepad++.
Нажимаю в нотепад++ ctrl+H, меню замены, меняю три пробела на два пробела, несколько раз, пока все не заменит, затем два пробела меняю на знак табуляции, в меню замены это будет выглядеть как “\t”, не забываем в serch mode выставить extended. Теперь копирую данные первого замера и вставляю в экселевскую табличку шаблон.
данные первого теста в ячейку - A1 (шесть столбцов данных)
второго - Q1
третьего - Z1
четвертого - AI1
Все данные тут же просчитаются и изменят соответственно графики (тяга, напряжение, ток, мощность, эффективность).
как ведите, некоторые данные для подсчета среднего значения можно просто исключить (например четвертый ряд при расчете среднего для эффективности), тем самым повысив качество отображаемой информации
Маленькие графики с левой стороны, это по четыре теста для каждого показания (тяга, напряжение с фильтром, ток с фильтром, мощность расчетная, эффективность расчетная).
Маленькие графики с правой стороны, это средний показатель из четырех тестов (тяга, напряжение с фильтром, ток с фильтром, мощность расчетная, эффективность расчетная).
Большой график в начале таблички, это значение эффективности полученное из средних значений тяги и мощности.
На второй страничке таблицы график с эффективностью и тягой.
памятка (требуется для цифрового фильтра Y(n) = (15*Y(n-1) + X(n)) >> 4 )
нашел интересную формулу для побитового сдвига в Excel
=ОТБР(A1/2^B1)
Число в А1, n в В1
проще говоря, можно напрочь все вычисления убить в ардуине и все возложить на Excel 😃
осталосЪ раскопать работу с компортом из экселя и написать макрос по вытряхиванию данных из ардумны …
тогда все можно будет делать прямо из экселя …
На том же процессинге есть осциллоскопы (ардуина - комп) можно оттуда подчерпнуть не? code.google.com/p/arduinoscope/
На том же процессинге есть осциллоскопы (ардуина - комп) можно оттуда подчерпнуть не? code.google.com/p/arduinoscope/
дык недавно линковал пример подобной интеграции
осталосЪ раскопать работу с компортом из экселя и написать макрос по вытряхиванию данных из ардумны …
тогда все можно будет делать прямо из экселя …
UP 😃
Здесь имеются некоторые сложности в получении эталонного значения по току. Если вы имеете какие либо предложения для решения данной проблемы, прошу высказываться. Пока более простого решения нет, в программе все таки имеется возможность калибровки. Для этого в разрыв питания регуля подключаем амперметр. Собираем ВМГ как для теста и нагружаем датчик тока путем раскрутки ВМГ. В режиме ввода эталонного значения тока можно нажимать клавиши “+” и “-” для задействования ВМГ в качестве нагрузки. Плюсом будем увеличивать обороты, минусом уменьшать. Но не забываем перед этими действиями откалибровать регулятор.
пока едет более чувствительный датчик тока, собрал схемку для настройки оного
руководствовался данной статьей
как видите собрал вторую схему, но в нашем варианте можно обойтись более простой
вторая схема проверена лично и работает на ура, но не увеличивайте нагрузку выше 5-7 ампер