Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.12.2016, 00:09   #1
chipaka
Новичок
Джуниор
 
Регистрация: 03.12.2016
Сообщений: 4
По умолчанию вывод среднего значения из массива

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

Код:
program bakometr;

const
   stNormal : byte = 1;
   stCalibr : byte = 2;
   AdrHi : byte = 3;
   litr : array [0..AdrHi] of byte = (0,10,20,30);

var
    C1 : sbit at porta.5;
    C2 : sbit at porta.2;
    SW : sbit at porta.3;

    i,j,cc: byte;
    V : word; absolute 0x30;
    Vhi : byte; absolute 0x31;
    VLo : byte; absolute 0x30;

    L10,L1:byte;
    dat : array [0..AdrHi] of byte;
    mode : byte;
    calibrN : byte;

procedure Led(i: byte);
begin
  if I=0 then begin
    portc:=%00000100;
    porta.4:=0;
  end;
  if I=1 then begin
    portc:=%00101101;
    porta.4:=1;
  end;
  if I=2 then begin
    portc:=%00100010;
    porta.4:=0;
  end;
  if I=3 then begin
    portc:=%00101000;
    porta.4:=0;
  end;
  if I=4 then begin
    portc:=%00001001;
    porta.4:=1;
  end;
  if I=5 then begin
    portc:=%00011000;
    porta.4:=0;
  end;
  if I=6 then begin
    portc:=%00010000;
    porta.4:=0;
  end;
  if I=7 then begin
    portc:=%00001101;
    porta.4:=0;
  end;
  if I=8 then begin
    portc:=%00000000;
    porta.4:=0;
  end;
  if I=9 then begin
    portc:=%00001000;
    porta.4:=0;
  end;
end;

procedure delay10;
begin
  delay_ms(10);
end;

procedure ReadData;
begin
  for i := 0 to AdrHi do dat[i]:=EEPROM_Read(i);
end;

begin

  porta := %00000000;
  trisa := %11001011;
  portc := %11111111;
  trisc := %00000000;
  wpua  := %00000001;
  cmcon := %00000111;
  ansel := %00000001;
  adcon0:= %01000000;
  adcon1:= %00110000;

  mode:=stNormal;
  ReadData;
  ADC_Init;
  i:=0;


  while true do
  begin
    inc(I);
    if mode = stNormal then
    begin
      if (i/127) and (V<5) then
      begin
        C1:=0;
        C2:=0;
      end;

      if i=0 then
      begin
        V:=ADC_Read(0);
        V:=V shr 2;
        if V>=dat[AdrHi]
          then V:=litr[adrHi]
          else
          begin
            if V<=dat[0]
              then V:=litr[0]
              else
              begin

                for j:=0 to AdrHi-1 do
                  if (V>=dat[j]) and (V<dat[j+1]) then cc:=j;
                if cc=AdrHi
                  then V:=Litr[AdrHi]
                  else
                  begin
                    V:= (V-dat[cc]);
                    j:=(Litr[cc+1]-Litr[cc]);
                    V:= V * j;
                    j:=(dat[cc+1]-dat[cc]);
                    V:= V / j;
                    V:= V + litr[cc];
                  end;
              end;
          end;

        L10:= v div 10;
        L1 := V mod 10;
        if (SW = 0) then
        begin
          C1:=1;
          C2:=1;
          portc:=%00111011;
          porta.4:=1;
          begin
            delay_ms(3000);
            if (SW = 0) then
            begin
              C1:=1;
              C2:=1;
              portc:=%00111110;
              porta.4:=1;
              calibrN:=0;
              mode:=stCalibr;
              delay10;
              repeat until SW = 1;
            end;
            delay10;
          end;
        end;
      end;
    end;
    if mode = stCalibr then
    begin
      L10:=litr[calibrN] div 10;
      l1:=litr[calibrN] mod 10;
      if i>127 then
      begin
        C1:=0;
        C2:=0;
      end;
      if SW = 0 then
      begin
        delay10;
        repeat until SW = 1;
        delay10;
        V:=adc_read(0);
        V:=V shr 2;
        EEPROM_Write(calibrN,VLo);
        inc(calibrN);
        if calibrN>AdrHi then
        begin
           C1:=1;
           C2:=1;
           portc:=%00111111;
           porta.4:=0;
           mode:= stNormal;
           CalibrN:=0;
           delay10;
           delay10;
           delay10;
           delay_ms(3000);
           ReadData;
        end;
      end;
    end;
delay_us(8000);
    if i.0 then begin
      C2 := 0;
      if (L10 = 0) then
        begin
          portc:= $3F;
          porta.4:=1;
        end
        else
      Led(L10);
      C1 := 1;
    end else
    begin
      C1 := 0;
      Led(L1);
      C2 := 1;
    end;
  end;
end.

Последний раз редактировалось Аватар; 04.12.2016 в 00:15.
chipaka вне форума Ответить с цитированием
Старый 04.12.2016, 11:42   #2
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,537
По умолчанию

Cудя по тому, что это прога реального времени для микроконтроллера, по тому, что написана она через }|{опу ( чего стоит только модуль Led ), по тому, что спросивший в этом не сечет at all, бо привел портянку целиком, не выделив проблемное место - ждать ответа до будущего лета... Такие вещи делаются обычно методом "скользящего окна" - заводится кольцевой буфер на N отсчетов, вычисляется среднее, при поступлении каждого следующего отсчета самый "старый" этим отсчетом вытесняется с соответствующей корректировкой среднего.
Код:
bufer: array[0..15] of integer ;
i,sum,median,next : integer ; 
...........................
 // Заполнение  массива
  sum := 0 ;
  i := 0 ;
  while (i<16)do
    begin
      // поступил следующий  отсчет
      sum := sum + next ;
      Inc (i) ;
    end ;
  median := sum div 16 ;
  i := 0 ;
 ...........................
  // Работа
      // поступил следующий  отсчет
  sum := sum - bufer[i] + next ;
  median := sum div 16 ;
  bufer[i] := next ;
  Inc (i) ;
  if i>15 then i := 0 ;
как-то так...
Но судя по вышеизложенному - для ТС это лекция об древнем Вавилоне на полузабытом диалекте китайского языка. Поэтому могу посоветовать в форум radiokot.ru, раздел "Есть работа". Там тусуются МК-шники. Если меньше 20$, посылают...
Любопытство гложет: это Микропаскаль для PIC ?

Последний раз редактировалось digitalis; 04.12.2016 в 11:48.
digitalis вне форума Ответить с цитированием
Старый 04.12.2016, 13:26   #3
chipaka
Новичок
Джуниор
 
Регистрация: 03.12.2016
Сообщений: 4
Печаль

В принципе не секу, но очень надо.
Было такое предложение:
"Так допишите усреднение. Ресурсов контроллера хватит. Надо сделать массив к примеру из 16 элементов и в него по кругу писать значения из АЦП, а на индикацию выдавать сумму всех элементов массива деленную на 16 ( shr 4 или div 16)

В обьявлениях
Код:
var
  V : array [0..15] of word;
  cV,i : byte;
  RealV : word;
В основном цикле
Код:
inc(cV);
  if cV>15 then cV:=0;
  V[cV]:= ADC_read;

  RealV:=0;
  for i:=0 to 15 do  RealV:=RealV + V[i];
  RealV:= RealV div 16;
Дальше RealV - на индикатор.
как то так."
Да это микропаскаль для пик

Последний раз редактировалось Вадим Мошев; 04.12.2016 в 13:55.
chipaka вне форума Ответить с цитированием
Старый 04.12.2016, 21:12   #4
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,537
По умолчанию

У меня все это сделано 100%. Вместо // поступил следующий отсчет записать next:= ADC_read; и вуаля . ( V[cV] в моем тексте bufer[i] )
А каждый раз считать 16 значений, выводить, обнулять и опять считать 16 - это опять же через то же место. Будут те же скачки, только с меньшей частотой . А посветовали 1:1 то же, что и я Но реализовано тупо : после добавления каждого нового значения пересчитывать сумму - абсурд. Еще раз : из суммы убираем самое "раннее" по времени значение, вместо него в сумму добавляем "свежий" отсчет и его же записываем на место убираемого. Сумму делим на 16.

Последний раз редактировалось digitalis; 04.12.2016 в 21:25.
digitalis вне форума Ответить с цитированием
Старый 04.12.2016, 21:54   #5
chipaka
Новичок
Джуниор
 
Регистрация: 03.12.2016
Сообщений: 4
По умолчанию

А не подскажите куда мне это в программе записать. Ну вехнюю часть понятно в var.
chipaka вне форума Ответить с цитированием
Старый 04.12.2016, 22:10   #6
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,537
По умолчанию

Нет, разбираться в этой левой ногой написанной проге - свыше моих сил. Достаточно посмотреть, как я говорил выше, процедуру Led ... Десяток if'ов вместо пары строчек : по индексу вытащить из 2 массивов по одному значению ...
digitalis вне форума Ответить с цитированием
Старый 05.12.2016, 08:27   #7
chipaka
Новичок
Джуниор
 
Регистрация: 03.12.2016
Сообщений: 4
По умолчанию

А за вознагрождение?
chipaka вне форума Ответить с цитированием
Старый 05.12.2016, 11:04   #8
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,537
По умолчанию

Нет, я работаю "под ключ" - у меня должен быть макет дивайса, исходники, компилятор, чтобы на выходе была полностью рабочая прога. Тем боле я с ПИКами и ихним МокроПаскалем никогда не работал. А как на мой взгляд, имея ТЗ, эту прогу проще переписать с нуля, чем ковыряться в этом ... шедевре.
Еще раз рекомендую - зайти на radiokot.ru - там несмотря на несерьезное название, тусуется много PIC=щиков. Могут и "за спасибо", если мелкая правка.

Последний раз редактировалось digitalis; 05.12.2016 в 12:08.
digitalis вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
С++ сортировка массива после нажатия клавиши и вывод значения lavrov.vjacheslav Помощь студентам 2 17.03.2015 19:30
С#. Нахождение среднего арифметического, вывод массива. Андрей Телепнёв Помощь студентам 1 27.08.2013 11:20
Вывод максимального значения из массива pascalabc.net Konstantin1706 Помощь студентам 9 16.09.2012 13:50
Вывод среднего значения ! BelialL PHP 7 21.06.2012 18:20
Вывод значения элементов массива valdemar593 Общие вопросы C/C++ 7 22.12.2009 21:37