Система автоматического тестирования ВМГ (народный проект)

sulaex

скетч с ремарками


#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");}
}
sulaex

все, закончил 😃
осталось поставить на стенд и проверить работу
если получится, протестирую в выходные


#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");}
}

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

заказал для стенда новую платку АЦП
и более чувствительный датчик тока

ЗЫ осталось самое сложное, написать документацию 😃

SergDoc
float CurrentValueRes = 0.0f;  // переменная с результатом для расчета тока (с плавающей точкой)

А то могут и непонятки начаться типа вместо 1 будет 0.999998…

sulaex

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

%	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;
}
SergDoc

Александр, эт вы на чём тестили двиг/проп - 400гр. тяги на 50%? почти 8гр/ватт

sulaex
SergDoc:

Александр, эт вы на чём тестили двиг/проп - 400гр. тяги на 50%? почти 8гр/ватт

это СанниСкаи 3508 580 с АПЦ 1238

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

на картинке показания напряжения и тока до (синий) и после фильтра (красный)

может тупо делать умножение показаний на коэффициент? 😃

например вот показания тока без множителя и с множителем 1,4

sulaex

для показаний фильтра по напряжению тогда такая формула (множителем не обойтись)

(значение напряжения с фильтра)*(1-(процент газа от 0 до 99)/10000)

sulaex

пример точности повторных измерений
графики по порядку
напряжение, ток, тяга
тестировалось на одном аккумуляторе 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

ЗЫ еще пару графиков мощность и эффективность ВМГ

sulaex

Под настроил стенд более точно, на сколько это возможно (датчик тока очень не подходящий, скоро будут нужные)
Обработанные данные со стенда (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");}
}

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

sulaex

Инструкция

Будьте внимательны при работе со стендом!!!

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");}
}
sulaex

Как быстро обработать данные полученные со стенда и предоставить их в удобочитаемом виде?

Я пользуюсь терминалом PuTTY. Запускаем тест под номером 2 (плавное измерение с шагом тяги от 0 до 100%) четыре раза подряд.
Верхний левый угол путти выбираем скопировать все данные в клипбоард. Дальше вставляю их в Notepad++.
Нажимаю в нотепад++ ctrl+H, меню замены, меняю три пробела на два пробела, несколько раз, пока все не заменит, затем два пробела меняю на знак табуляции, в меню замены это будет выглядеть как “\t”, не забываем в serch mode выставить extended. Теперь копирую данные первого замера и вставляю в экселевскую табличку шаблон.

данные первого теста в ячейку - A1 (шесть столбцов данных)
второго - Q1
третьего - Z1
четвертого - AI1

Все данные тут же просчитаются и изменят соответственно графики (тяга, напряжение, ток, мощность, эффективность).

как ведите, некоторые данные для подсчета среднего значения можно просто исключить (например четвертый ряд при расчете среднего для эффективности), тем самым повысив качество отображаемой информации

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

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

На второй страничке таблицы график с эффективностью и тягой.

sulaex

памятка (требуется для цифрового фильтра Y(n) = (15*Y(n-1) + X(n)) >> 4 )

нашел интересную формулу для побитового сдвига в Excel
=ОТБР(A1/2^B1)
Число в А1, n в В1

проще говоря, можно напрочь все вычисления убить в ардуине и все возложить на Excel 😃

Gapey

осталосЪ раскопать работу с компортом из экселя и написать макрос по вытряхиванию данных из ардумны …
тогда все можно будет делать прямо из экселя …

sulaex
Gapey:

осталосЪ раскопать работу с компортом из экселя и написать макрос по вытряхиванию данных из ардумны …
тогда все можно будет делать прямо из экселя …

strokescribe.com/ru/serial-port-programming.html

sulaex

UP 😃

sulaex:

Здесь имеются некоторые сложности в получении эталонного значения по току. Если вы имеете какие либо предложения для решения данной проблемы, прошу высказываться. Пока более простого решения нет, в программе все таки имеется возможность калибровки. Для этого в разрыв питания регуля подключаем амперметр. Собираем ВМГ как для теста и нагружаем датчик тока путем раскрутки ВМГ. В режиме ввода эталонного значения тока можно нажимать клавиши “+” и “-” для задействования ВМГ в качестве нагрузки. Плюсом будем увеличивать обороты, минусом уменьшать. Но не забываем перед этими действиями откалибровать регулятор.

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

руководствовался данной статьей

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

ARXITEKTOR

Вот пришла в голову идея а что если совместно с андурино использовать среду
LabVIEW там и с андуриной работать можно и математику возложить на комп.

Nesenin

дык используйте. все поделки так и делаю arduino + labview. отправляю команды. читаю данные. хошь графики строй хошь 3D модели. можно интерполяцию прикрутить. запись в базу\чтение сравнение. ммм

по поводу серво сигнала на arduino. он не аппаратный. в смысле не по прерываниям от таймера работает. от того может дергать туда-сюда. для данной темы наверно не сильно актуально, но вообще есть средство arduiniana.org/libraries/pwmservo/ мож кому пригодится.

1 month later
Nesenin

sulaex, возможно у вас не точна схема передачи усилия на тензодатчик. на вид присутствует “рычаг”, см. ось двигателя имеет небольшой вылет над ножкой. я тут как рас подобную схему о 2х опорах ваяю. и заметил что даже небольшого смещения точки приложения силы и точки опоры, хватает на возникновение ошибки. а у вас еще 1 опора усилие оказывает.
может все ж сделать площадку на самой конструкции датчика и туда уже движок крепить? правда не ясно как вибрация повлияют.

Nesenin

фух! получил первый результат

эт без фильтров. мышкой крутил уровень сервосигнала. внизу на графике видно как он рос.
поздно прочел про точность датчика тока. купил ACS758LCB-050 B надо было с U(униполярный)
выход с датчика тока сначала без обвеса подключил
см

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