Запись массива с типом данных float и вывод его в com-порт

Aspeed
Offline
Зарегистрирован: 07.08.2018

Доброго времени суток, хотел сделать себе приблуду для страйкбольного привода чтобы мог стрелять очередями по 3 , 5 ... чтобы число выстрелов можно было прописать в програме...А также чтобы цыкл совершался полностью т. е. пружина должна быть аслаблена. НО что-то не выходит, в програмировании я новичок не судите строго за код.  В основе всего сидит датчик тока ASC 712 он постоянно считывает показания тока, по этим показаниям по задумке программа отслеживает цикл (см скриншот ниже)и считает их колличество. я попытался вывести значения в ком порт при массиве float одни нули были, перевел данные float в int  стали выводиться странные числа (см скриншот ниже).

 
 
/*
AEG контроллер
*/
const int sensorPin = A0;
int mVperAmp = 100; //коэф перевода для датчика тока 100 for 20A 
int RawValue= 0;
int ACSoffset = 2500; // Значение напряжение м мВ при 0А.
float Voltage = 0;    // Напряжение в мВ
float Amps = 0;       //Сила тока
#define Pin_Button 3 //Пин к которому привязываем кнопку 
#define Pin_MOSFET 4 //Пин к которому привязываем мосфет транзистор 
#define Pin_Button_2 2 //Пин к которому привязываем кнопку которая упровляет колличеством выстрелов
#define quantity_shots 4 // Коичество выстрелов в очереди
boolean x = 0; //перепенная вкл/выкл режима стрелбы очередми 
boolean flag = 0; // флажок для управления кнопкой стрельбы очерередями 
boolean flag_2=0; //флажок для управление отсечкой огня 
byte shots = 0; //Считает количество выстрелов 

//----------------------------------------ФИЛЬТР ПО СТРЕДНЕМУ ЗНАЧЕНИЮ---------------------------------------
 // функция считывает аналоговый вход заданное количество раз
// и возвращает отфильтрованное значение
int readMean(int pin, int samples){
  // переменная для хранения суммы считанных значений
  int sum = 0;
  // чтение и складывание значений
  for (int i = 0; i < samples; i++){
    sum = sum + analogRead(pin);
  }
  // делим сумму значений на количество измерений
  sum = sum/samples;
  // возвращаем среднее значение
  return sum;
}
//----------------------------------------МЕДИАННЫЙ ФИЛЬТР---------------------------------------------------
// функция считывает аналоговый вход заданное количество раз
// и возвращает медианное отфильтрованное значение
int readMedian (int pin, int samples){
  // массив для хранения данных
  int raw[samples];
  // считываем вход и помещаем величину в ячейки массива
  for (int i = 0; i < samples; i++){
    raw[i] = analogRead(pin);
  }
  // сортируем массив по возрастанию значений в ячейках
  int temp = 0; // временная переменная

  for (int i = 0; i < samples; i++){
    for (int j = 0; j < samples - 1; j++){
      if (raw[j] > raw[j + 1]){
        temp = raw[j];
        raw[j] = raw[j + 1];
        raw[j + 1] = temp;
      }
    }
  }
  // возвращаем значение средней ячейки массива
  return raw[samples/2];
}

void setup(){ 
 Serial.begin(115200);
 pinMode(Pin_Button, INPUT_PULLUP);// Используем 3 пин для снятия значений с кнопки
 pinMode(Pin_MOSFET, OUTPUT); // Пин (4) который открывает и закрывает мосфет транзистор
 pinMode(Pin_Button_2, INPUT_PULLUP); // Используем 2 пин для снятия значений с кнопки
}

void loop(){
  //---------------------------------РАСЕТ ЗНАЧЕНИЯ СИЛЫ ТОКА----------------------------------------------
 RawValue = readMedian(sensorPin, 15);// Присваиваем переменной отфильтрованные значения по медианному фильтру
 Voltage = (RawValue / 1024.0) * 5000; // Формула для подсчета напряжения в мВ
 Amps = ((Voltage - ACSoffset) / mVperAmp);//Формула для подсчета силы тока в А


 boolean butt=0;// переменная хранящая состояние кнопки
 butt=!digitalRead(Pin_Button);//считывание с пина кнопки значений(инвертируем сигнал т.к. используем INPUT_PULLUP)
 boolean butt_2 = 0; //Переменная хранящая состояние кнопки №2(кнопкп переключения режимов огня)
 butt_2=!digitalRead(Pin_Button_2);

 // Управление кнопкой стрельбы очередями
 if (butt_2==1 && flag==0){
  flag=1;
  x=!x;
 }
 if(butt_2==0 && flag==1){
  flag=0;
  }

   int lol=0;
   lol=int(Amps);//переписывает float в int
   //Serial.println(lol);
   //---------------------------------АВТОМАТИЧЕСКАЯ СТРЕЛЬБА--------------------------------------------------
  //Условие при котором двигатель включон
  if(butt==1 && x==0){digitalWrite(Pin_MOSFET,HIGH);
  }
  //----------------------------------СТРЕЛЬБА ОЧЕРЕДЯМИ(не работает)-------------------------------------------------------

  else if (butt==1 && x==1 && flag_2==0){digitalWrite(Pin_MOSFET, HIGH);
    int raw_3[10];
    for( int i=0; i<10; i++){
      raw_3[i]=lol; 
     delay(30);
      if (raw_3[i+1]<raw_3[i]){shots++;        // условие которае считает количество выстрелов и дает отсечку 
        if (shots >= quantity_shots && butt==1){ 
          digitalWrite(Pin_MOSFET, LOW); flag_2=1;
        shots=0;// обнуляем счетчик
          }
        } 
     }
  }
  else if (butt==0 && x==1 && flag_2==1){
    flag_2=0;
  }
  //-----------------------------------------------ТОРМОЗ---------------------------------------------------
  else if (butt==0){// Если спуск отпущен отключает мосфет 
     int raw_2[10];
  // Условие для поиска падения силы тока  
    for(int i=0; i<10; i++){    
      raw_2[i]=lol;
        if(raw_2[i+1]<raw_2[i] && butt==0){
          digitalWrite(Pin_MOSFET, LOW);
           //Serial.println(raw_2[10]);
      }
    }
  }
 //Serial.println(shots); 
 //Serial.println(butt);
 //Serial.println(x);
 //Serial.print("\t Без фильтра = " ); //показать не фильтрованные значения 
 //Serial.print(RawValue);//показать не фильтрованные значения 
  
 //Serial.print("\t mV = "); // показать значение напряжения в мВ
//Serial.print(Voltage,3); //"3"- колличество знаков после запятой

 //Serial.print("\t A = "); // показать значения силы тока 
 Serial.println("$");
 Serial.println(Amps,3); // "3"- колличество знаков после запятой
 Serial.println(";");

 // Вывод фильтрованных значений
 // выводим среднеизмеренное значение
  //Serial.print("\t Cреднее= ");
  //Serial.print(readMean(sensorPin, 15));

  // выводим медианное отфильтрованное значение
  //Serial.print("\t Медианное= ");
  //Serial.print(readMedian(sensorPin, 15));
  
 delay(10); 
  
}

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Код не соответсвует тому, что выводится - это печатал другой код.

Давайте-ка ещё раз код и ЕГО печать. Только печать не картинкой, а текстом (копипастом).

Aspeed
Offline
Зарегистрирован: 07.08.2018
/*
AEG контроллер
*/
const int sensorPin = A0;
int mVperAmp = 100; //коэф перевода для датчика тока 100 for 20A 
int RawValue= 0;
int ACSoffset = 2500; // Значение напряжение м мВ при 0А.
float Voltage = 0;    // Напряжение в мВ
float Amps = 0;       //Сила тока
#define Pin_Button 3 //Пин к которому привязываем кнопку 
#define Pin_MOSFET 4 //Пин к которому привязываем мосфет транзистор 
#define Pin_Button_2 2 //Пин к которому привязываем кнопку которая упровляет колличеством выстрелов
#define quantity_shots 4 // Коичество выстрелов в очереди
boolean x = 0; //перепенная вкл/выкл режима стрелбы очередми 
boolean flag = 0; // флажок для управления кнопкой стрельбы очерередями 
boolean flag_2=0; //флажок для управление отсечкой огня 
byte shots = 0; //Считает количество выстрелов 

//----------------------------------------ФИЛЬТР ПО СТРЕДНЕМУ ЗНАЧЕНИЮ---------------------------------------
 // функция считывает аналоговый вход заданное количество раз
// и возвращает отфильтрованное значение
int readMean(int pin, int samples){
  // переменная для хранения суммы считанных значений
  int sum = 0;
  // чтение и складывание значений
  for (int i = 0; i < samples; i++){
    sum = sum + analogRead(pin);
  }
  // делим сумму значений на количество измерений
  sum = sum/samples;
  // возвращаем среднее значение
  return sum;
}
//----------------------------------------МЕДИАННЫЙ ФИЛЬТР---------------------------------------------------
// функция считывает аналоговый вход заданное количество раз
// и возвращает медианное отфильтрованное значение
int readMedian (int pin, int samples){
  // массив для хранения данных
  int raw[samples];
  // считываем вход и помещаем величину в ячейки массива
  for (int i = 0; i < samples; i++){
    raw[i] = analogRead(pin);
  }
  // сортируем массив по возрастанию значений в ячейках
  int temp = 0; // временная переменная

  for (int i = 0; i < samples; i++){
    for (int j = 0; j < samples - 1; j++){
      if (raw[j] > raw[j + 1]){
        temp = raw[j];
        raw[j] = raw[j + 1];
        raw[j + 1] = temp;
      }
    }
  }
  // возвращаем значение средней ячейки массива
  return raw[samples/2];
}

void setup(){ 
 Serial.begin(115200);
 pinMode(Pin_Button, INPUT_PULLUP);// Используем 3 пин для снятия значений с кнопки
 pinMode(Pin_MOSFET, OUTPUT); // Пин (4) который открывает и закрывает мосфет транзистор
 pinMode(Pin_Button_2, INPUT_PULLUP); // Используем 2 пин для снятия значений с кнопки
}
 
void loop(){
  //---------------------------------РАСЕТ ЗНАЧЕНИЯ СИЛЫ ТОКА----------------------------------------------
 RawValue = readMedian(sensorPin, 15);// Присваиваем переменной отфильтрованные значения по медианному фильтру
 Voltage = (RawValue / 1024.0) * 5000; // Формула для подсчета напряжения в мВ
 Amps = ((Voltage - ACSoffset) / mVperAmp);//Формула для подсчета силы тока в А

 
 boolean butt=0;// переменная хранящая состояние кнопки
 butt=!digitalRead(Pin_Button);//считывание с пина кнопки значений(инвертируем сигнал т.к. используем INPUT_PULLUP)
 boolean butt_2 = 0; //Переменная хранящая состояние кнопки №2
 butt_2=!digitalRead(Pin_Button_2);
 
 // Управление кнопкой стрельбы очередями
 if (butt_2==1 && flag==0){
  flag=1;
  x=!x;
 }
 if(butt_2==0 && flag==1){
  flag=0;
  }

   int lol=0;
   lol=int(Amps);//переписывает float в int
   //Serial.println(lol);
   //---------------------------------АВТОМАТИЧЕСКАЯ СТРЕЛЬБА--------------------------------------------------
  //Условие при котором двигатель включон
  if(butt==1 && x==0){digitalWrite(Pin_MOSFET,HIGH);
  }
  //----------------------------------СТРЕЛЬБА ОЧЕРЕДЯМИ(не работает)-------------------------------------------------------
 
  else if (butt==1 && x==1 && flag_2==0){digitalWrite(Pin_MOSFET, HIGH);
    int raw_3[10];
    for( int i=0; i<10; i++){
      raw_3[i]=lol; 
     delay(30);
      if (raw_3[i+1]<raw_3[i]){shots++;        // условие которае считает количество выстрелов и дает отсечку 
        if (shots >= quantity_shots && butt==1){ 
          digitalWrite(Pin_MOSFET, LOW); flag_2=1;
        shots=0;// обнуляем счетчик
          }
        } 
     }
  }
  else if (butt==0 && x==1 && flag_2==1){
    flag_2=0;
  }
  //-----------------------------------------------ТОРМОЗ---------------------------------------------------
  else if (butt==0){// Если спуск отпущен отключает мосфет 
     int raw_2[10];
  // Условие для поиска падения силы тока  
    for(int i=0; i<10; i++){    
      raw_2[i]=lol;
        if(raw_2[i+1]<raw_2[i] && butt==0){
          digitalWrite(Pin_MOSFET, LOW);
           Serial.println(raw_2[10]);
           Serial.println("---------------------");
      }
    }
  }
 //Serial.println(shots); 
 //Serial.println(butt);
 //Serial.println(x);
 //Serial.print("\t Без фильтра = " ); //показать не фильтрованные значения 
 //Serial.print(RawValue);//показать не фильтрованные значения 
  
 //Serial.print("\t mV = "); // показать значение напряжения в мВ
//Serial.print(Voltage,3); //"3"- колличество знаков после запятой

 //Serial.print("\t A = "); // показать значения силы тока 
 //Serial.println("$");
 //Serial.println(Amps,3); // "3"- колличество знаков после запятой
 //Serial.println(";");

 // Вывод фильтрованных значений
 // выводим среднеизмеренное значение
  //Serial.print("\t Cреднее= ");
  //Serial.print(readMean(sensorPin, 15));

  // выводим медианное отфильтрованное значение
  //Serial.print("\t Медианное= ");
  //Serial.print(readMedian(sensorPin, 15));
  
 delay(10); 
  
}
 
 
Вот это выводит:
 
2265
---------------------
2265
---------------------
2265
---------------------
2265
---------------------
2265
---------------------
2265
---------------------
2265
---------------------
2265
---------------------
2265
---------------------
2265
---------------------
 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Массив raw_2 описан в строке 115 как

int raw_2[10];

Значит в нём 10 элементов с 0-го по 9-ый.

А в строке 121 Вы выводите на печать 10-ый элемент

Serial.println(raw_2[10]);

которого в данном массиве попросту нет. И что Вы надеетесь увидеть?

Кстати, в строке 119 тоже есть выход за границы этого массива, т.к. i меняется от 0 до 9, а Вы исапользуете i+1

Aspeed
Offline
Зарегистрирован: 07.08.2018

все ясно, я думал, что вывожу 10 элементов массива :( 

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

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

за рание благодарю :)

b707
Offline
Зарегистрирован: 26.05.2017

Aspeed пишет:

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

почему нельзя-то? - можно, только за пределы массива не выходите

Aspeed
Offline
Зарегистрирован: 07.08.2018

Тогда как понять, что я выхожу за пределы массива, или проще не задавать границы int raw_2[]; , а в конце цикла вернуть колличество байт командой sizeof(), только я немного не понимаю как ее внедрить... 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Aspeed пишет:

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

Ну, так и понять. Если он у Вас объявлен как [10], то следите, чтобы индекс был от 0 до 9.

Aspeed пишет:

или проще не задавать границы int raw_2[]; , а в конце цикла вернуть колличество байт командой sizeof(), только я немного не понимаю как ее внедрить... 

Простите, это бред. А память то под массив кто выделит? Надо сначала указать сколько там элементов (выделить память) а потом уж с ними рабботать, а не наоборот. Почитайте про работау с массивами в Си. Иинформации навалом.

 

Aspeed
Offline
Зарегистрирован: 07.08.2018

Хорошо :) с массивами я разберусь, но вот я не понимаю почему не работает мой режим стрельбы очередими. Там смысл такой:  наполняеться массив данными с токового датчика и его элементы сравниваются и получаеться пока двигаетль взводит пружину ток растет, после происходит выстрел и двигатель работает в холостую (ток падает), пока секторная шестерня снова ( провернувший) не начнет взводить пружину и так по кругу. В это время программа считает количесво этих "спадов"(выстрелов) и сравнивает с тем количеством выстрелов которые указаны(пользователь сам указывает нужное ему кол-во). после достижения этого числа, прога должна остановиться и ждать пока снова не нажмут на спуск.

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

Aspeed
Offline
Зарегистрирован: 07.08.2018

Извините, я не понимаю, как я могу выйти за пределы массива, если он находится в цикле который подставляет индексы 0, 1, 2.... 9 и так покругу, массив просто перезаписываеться (ну покрайней мере, я так думаю) 
 
Просто мне нужно чтобы массив "бежал" по данным идущим с датчика ( Бежит и сканирует данные)

данные с датчика -->========[==========]============--> 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Aspeed пишет:

Извините, я не понимаю, как я могу выйти за пределы массива, если он находится в цикле который подставляет индексы 0, 1, 2.... 9 и так покругу, 

Но Вы ведь используете i+1 в качестве индекса массива в строке №119! А чему, по Вашему, равно i+1, когда i равно 9? Вот Вы и вылезли, чего Вы тут не понимаете?

Aspeed
Offline
Зарегистрирован: 07.08.2018

Извините пожалуйста, я достал своими вопросами, но я сталкнулся еще с 1 проблемой. Почему  к переменной shots пребавляется 1 если условие не выполняеться. Вот что выводится: 

0.195312
1
0.195312
0.195312
0.195312
0.195312
0.195312
0.195312
0.195312
0.195312
0.195312
22.265625
2
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
3
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
22.265625
я уже ставил разные условия и больше, и меньше, и не равно, но эффект нулевой.
 
 //----------------------------------СТРЕЛЬБА ОЧЕРЕДЯМИ(не работает)-------------------------------------------------------
 
  else if (butt==1 && x==1 && flag_2==0){digitalWrite(Pin_MOSFET, HIGH);
    float raw_3[10];
    for( int i=0; i<10; i++){
      raw_3[i]=Amps; 
      Serial.println(raw_3[i],6);
       // Сода можно списать задержку на 30 мс и будет по 4 выстрела
      if (raw_3[i]<raw_3[i-1]){shots++;        // условие которае считает количество выстрелов и дает отсечку 
       Serial.println(shots);
        if (shots >= quantity_shots){ 
          digitalWrite(Pin_MOSFET, LOW);
          flag_2=1;
          shots=0;// обнуляем счетчик
          }
        } 
     }
  }
  else if (butt==0 && x==1 && flag_2==1){
    flag_2=0;
  }

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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