Обсуждаем контроллеры компании Atmel.
Ответить

Re: Измерение скорости автомобиля по штатному датчику

Пт сен 08, 2023 00:25:48

ну дык, сенсор самое главное и интересное и сложное и есть :)

Re: Измерение скорости автомобиля по штатному датчику

Пт сен 08, 2023 00:56:41

Martian писал(а):... сенсор самое главное и интересное и сложное и есть :)
Имхо главное это то, какая преследуется цель и что для решения задачи есть на данный момент в тумбочке. :)
Пардон - похоже уже флудим в теме. Если есть вопросы, плиз в личку.

Re: Измерение скорости автомобиля по штатному датчику

Пт сен 08, 2023 08:24:12

Ненене, тоже очень интересно. С пробегом ещё более-менее понятно, а как топливо измеряли?

Re: Измерение скорости автомобиля по штатному датчику

Пт сен 08, 2023 22:06:37

>TEHb<, см. личку.

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 12:32:07

Может быть я туплю, конечно, но дела таковы: переключил я таймер 1 в режим захвата. Написал такой код
Спойлер
Код:
void tim1_ini(void)
{
        // Частота кварца 20000000Гц
   TCCR1A=0x00; // Normal mode
   TCCR1B &= ~((1<<WGM12)|(1<<WGM13)|(1<<CS11)); // Делитель 1024. Частота тактирования после делителя 19530 Гц.
   TCCR1B |= ((1<<CS12)|(1<CS10)); // Захват по спаду
   TCNT1=0;
   TIMSK1 |=(1<<ICIE1); // Разрешение прерывания по захвату
}

volatile uint16_t cnt=0;
uint16_t frec=0;

ISR(TIMER1_CAPT_vect)
{
   TCNT1=0;
   cnt=ICR1;
   
}

int main(void)
{
tim1_ini();
sei();

While(1)
  {
      frec=19530/cnt; // Здесь понятно, что на ноль делить нельзя, просто для понимания.
   sprintf(val_1,"%.0d",frec);
  }
}

Подал с генератора 113 Гц. Получил на экране число 682. И это не дребезг. Период меандра 113 Гц = 8.8 мС. Период частоты тактирования таймера 19530Гц=51.2 мкС. Исходя из этого за 1 период частоты 113 Гц должно посчитаться примерно 170 тиков. Но не 682. По ходу с математикой может я протупливаю?

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 12:55:24

Изображение

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 13:00:50

mont-oriol, спасибо тебе огроменное! Моя невнимательность привела меня к такому гемморру...

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 16:05:47

Датчик представляет из себя обычный геркон, который замыкает подтянутый к 5 вольтам вход приборки на землю.
...
Поставил на вход кондер 0.1 мкф и на землю.

Конденсатор в параллель геркону может сократить ресурс контактов геркона. Я бы примерно так сделал:
Изображение

Добавлено after 19 minutes 50 seconds:
У SMAJ5.0A ток утечки великоват, нужно что-то другое, выбор есть.

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 16:43:23

Попробую для начала без кондера включить noice canceler, хотя наверно не поможет. Там провода от датчика проходят рядом с трамблером. Он то скорее всего и наводит шороху. Если не поможет, тогда по железу буду дальше кумекать. Но там вроде идет сигнал на UAF 2115. Думаю, нет там таких токов огромных. Я просто не знал, что кондер в параллель геркону приводит к снижению ресурса.

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 21:11:36

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

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 22:13:07

конденсатор большим током разряжается через него.

Да, спасибо. Я понял. Кондер заряжается в любом случае через резистор подтяжки. При замыкании геркона кондер через него разряжается на массу.

Добавлено after 1 minute 31 second:
Завтра поинтересуюсь еще парой вопросов)

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 22:16:20

Один из них будет про правильное название конденсатора?

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 22:25:40

В догонку... За счет некоторой протяженности проводов и с учетом их какой-то индуктивности возможно ли нивелирование этих эффектов? Понятно, что провода также привносят свою емкостную составляющую.

Добавлено after 2 minutes 9 seconds:
Один из них будет про правильное название конденсатора?


Я знаю его истинное имя-капацитор. Ваш сарказм не уместен

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 22:38:08

Это Ваше уродование слов не уместно. Наверняка, когда к доктору или полицейскому приходите, внезапно грамотность просыпается, но тут-то кто? Тут гопники и быдло, недостойное уважения.
И я спрашивал без сарказма.

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 22:51:28

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

Добавлено after 5 minutes 15 seconds:
Тут гопники и быдло, недостойное уважения.

У Вас низкая самооценка. К тому же под свою самооценку вы подвели всех участников форума, обобщив их. Не нужно так делать. Вы не можете решать за всех. Обратитесь к психологу, он вам поможет. Наверно...

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 23:03:51

За счет некоторой протяженности проводов и с учетом их какой-то индуктивности возможно ли нивелирование этих эффектов?

Конечно. Но всего один резистор хотя бы сотню ом последовательно с конденсатором это всё гарантированно убирает. Стоит ли тут экономить?

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 09, 2023 23:14:59

Да нет, конечно. Не стоит. Просто плата сделана, распаяна. Буду переделывать. Но есть некоторые вопросы. Озвучу позже. Возможнр завтра. Времени не хватает...

Re: Измерение скорости автомобиля по штатному датчику

Сб сен 16, 2023 20:40:14

Всем доброго здравия!
Разобрался я с выводом пробега. Все сделал через целочисленные значения. Не то, что хотелось, но float рассчитывается очень неважно. У меня возник еще один вопрос по поводу алгоритма обработки нажатия кнопки. Суть такова, что есть "теневое" меню, где можно корректировать данные в зависимости от пробега авто, производительности форсунки, от емкости топливного бака, от количества импульсов датчика скорости на 1000 метров (комплектации разные) и запоминать их в EEPROM для последующих расчетов. Я набросал некоторые функции по коррекции этих данных, но вопрос уперся в обработку нажатия кнопки. Хочу отметить то, что кнопка всего ОДНА. И нужно как-то выкрутиться. Функцию обработки нажатия кнопки я честно признаюсь украл. Проблема сейчас в том, что при двойном нажатии ловится сначала одиночное нажатие, потом двойное. Код нажатия одиночного 03, двойного 05. Код под спойлером.
Спойлер
Код:

ISR(TIMER0_OVF_vect)  // Прерывание по Таймеру 0
{
   //TCNT0=131;  // 8MHz
   TCNT0=178;  // 20 MHz
   millis++; // Инкрементируем каждую миллисекунду
}

/*
 * button.c
 *
 * Created: 17.04.2023 18:58:14
 *  Author: ADMIN
 */
#include "button.h"

uint8_t button1S;   // храним состояния кнопок (S - State)
uint8_t button1F;   // флажки кнопок (F - Flag)
uint8_t button1R;   // флажки кнопок на отпускание (R - Release)
uint8_t button1P;   // флажки кнопок на нажатие (P - Press)
uint8_t button1H;   // флажки кнопок на удержание (многократный вызов) (H - Hold)
uint8_t button1HO;  // флажки кнопок на удержание (один вызов при нажатии) (HO - Hold Once)
uint8_t button1D;   // флажки кнопок на двойное нажатие (D - Double)
uint8_t button1DP;  // флажки кнопок на двойное нажатие и отпускание (D - Double Pressed)

#define DOUBLE_TIMER 500   // время (мс), отведённое на второе нажатие
#define HOLD 2000           // время (мс), после которого кнопка считается зажатой
#define DEBOUNCE 50        // (мс), антидребезг
uint32_t button1_timer; // таймер последнего нажатия кнопки
uint32_t button1_double; // таймер двойного нажатия кнопки

uint8_t buttons(void)
{
   uint8_t bt1=0; // Будем возвращать результат в этой переменной
   
   if (BitIsClear(BUT1_PIN,BUT1)) button1S=1;
   else button1S=0; // Состояние кнопки
   
   // нажали (с антидребезгом)
   if (button1S && !button1F && millis - button1_timer > DEBOUNCE)
   {
      button1F = 1; // Установим флаг кнопки
      button1HO = 1; // флаг на удержание
      button1_timer = millis; // таймер последнего нажатия кнопки
      bt1=1;
   }
   // если отпустили до hold, считать отпущенной
   if (!button1S && button1F && !button1R && !button1DP && millis - button1_timer < HOLD)
   {
      button1R = 1; // флаг на отпускание
      button1F = 0; //флаг кнопки
      bt1=2;
      button1_double = millis; // Таймер двойного нажатия кнопки
   }
   
   // если отпустили и прошло больше double_timer, считать 1 нажатием
   if (button1R && !button1DP && millis - button1_double > DOUBLE_TIMER)
   {
      button1R = 0;
      button1P = 1;
      bt1=3;
   }
   
   // если отпустили и прошло меньше double_timer и нажата снова, считать что нажата 2 разa
   if (button1F && !button1DP && button1R && millis - button1_double < DOUBLE_TIMER)
   {
      button1F = 0;
      button1R = 0;
      button1DP = 1;
      bt1=4;
   }
   
   // если была нажата 2 разa и отпущена, считать что была нажата 2 раза
   if (button1DP && millis - button1_timer < HOLD)
   {
      button1DP = 0;
      button1D = 1;
      button1_timer = millis;
      bt1=5;
   }
   
   // Если удерживается более hold, то считать удержанием
   if (button1F && !button1D && !button1H && millis - button1_timer > HOLD)
   {
      button1H = 1;
      bt1=6;
   }
   
   // Если отпущена после hold, то считать, что была удержана
   if (!button1S && button1F && millis - button1_timer > HOLD)
   {
      button1F = 0;
      button1H = 0;
      button1_timer = millis;
      bt1=7;
   }
   
   // отработка режимов (опускание флага обязательно!)
  if (button1P) button1P = 0;   
  if (button1D) button1D = 0;   
  if (button1H && button1HO) button1HO = 0;
  if (button1H) button1H = 0;
 
  return bt1; 
}


/*
 * Dark_menu.c
 *
 * Created: 18.08.2023 18:05:08
 *  Author: ADMIN
 */
#include "dark_menu.h"

uint8_t main_dark_mode=0; // Переменная для хранения режима теневого меню.
uint8_t sub_mode=0; // флаг входа в подменю
uint8_t edit_mode=0; // пока не используется
uint8_t b=0; // счетчик нажатия кнопки
uint8_t pr_var=0; // Переменная, которая в подменю будет инкрементироваться по нажатию кнопки от 0 до 9
uint8_t pr[6]={0,1,2,3,4,5}; // Массив для разбивки пробега(или еще чего-то) поразрядно для возможности коррекции(тест)

void main_text(void) // Основной текст меню
 // Построчный вывод пунктов меню
{
   print_string_5x8(11,0,"MILEAGE(km)");  // Вывод типа " -> MILLEAGE(km)"
   print_string_5x8(11,1,"SPEED SENSOR(imp)");
   print_string_5x8(11,2,"INJECTOR (cc/min)");
   print_string_5x8(11,3,"FUEL TANK MIN NOW");
   print_string_5x8(11,4,"FUEL TANK MAX NOW");
}

void pointer_clear(void)  // очистка стрелочки
{
   for(uint8_t i=0; i<5; i++)
   {
      print_string_5x8(0,i,"  ");
   }
   
}

void main_dark_menu(void)
{
       screen_clear();
   if (cod==3) // Если нажали и отпустили кнопку
   {
      main_dark_mode++; // Бегаем по основному меню
      if(main_dark_mode>4) main_dark_mode=0; // Бегаем по кругу
   }
   switch (main_dark_mode)
   {
       case 0:             // коррекция пробега
              pointer_clear();                         // Очистка стрелочки
                print_string_5x8(0,main_dark_mode,"->"); // Cтрелка на нулевой строке, т.к. mode_1 сейчас равен нулю.
            main_text();                             // Выводим все пункты основного меню
            
            if (cod==5)                              // Если двойное нажатие, заходим в подменю
            {
               cod=0;                               // Сразу обнулим код нажатия кнопки
               screen_clear();                      // Очистим экран
               sub_mode=1;                          // Зайдем в режим подменю
               
               
               while(sub_mode)
               { 
                  cod=buttons();
                   print_string_5x8(16,2,"SET MILEAGE(km)"); // Тут печать пояснительного текста
                   print_string_5x8(16,3,"x100000----x1");
                   print_string_5x8(16,4,"ALL 6 DIGIT");
                  screen_update();
                  correction(6,16,pr); // Заходим в функцию коррекции величин
                  
                  if (cod==6) // Нужно как-то выйти из цикла..
                  {
                     sub_mode=0;
                  }
                  
                  
                }
            }
            break;   
            
      case 1:                    // Speed sensor
              pointer_clear();
              print_string_5x8(0,main_dark_mode,"->");
            main_text();
            if (cod==5)
            {
               cod=0;                               // Сразу обнулим код нажатия кнопки
               screen_clear();                      // Очистим экран
               sub_mode=1;
               
               while(sub_mode)
               {
                  cod=buttons();
                  print_string_5x8(16,2,"SET SPEED SENSOR");
                  print_string_5x8(16,3,"IMP/1000m");
                  print_string_5x8(16,4,"ALL 4 DIGIT");
                  screen_update();
                  if (cod==6)
                  {
                     sub_mode=0;
                  }
                  
               }
            }
            break;
            
      case 2:           // Injector
              pointer_clear();
              print_string_5x8(0,main_dark_mode,"->");
              main_text();
            if (cod==5)
            {
               cod=0;                               // Сразу обнулим код нажатия кнопки
               screen_clear();                      // Очистим экран
               sub_mode=1;
               
               while(sub_mode)
               {
                  cod=buttons();
                  print_string_5x8(16,2,"SET INJECTOR");
                  print_string_5x8(16,3,"PRODUCTIVITY");
                  //print_string_5x8(16,4,"");
                  screen_update();
                  if (cod==6)
                  {
                     sub_mode=0;
                  }
               }
            }
              break;
            
      case 3:        // Fuel min
              pointer_clear();
              print_string_5x8(0,main_dark_mode,"->");
              main_text();
            
            if (cod==5)
            {
               cod=0;                               // Сразу обнулим код нажатия кнопки
               screen_clear();                      // Очистим экран
               sub_mode=1;
               
               while(sub_mode)
               {
                  cod=buttons();
                  print_string_5x8(16,2,"PRESS BUTTON ");
                  print_string_5x8(16,3,"FOR MEMORY");
                  print_string_5x8(16,4,"ENTRIES MIN");
                  screen_update();
                  if (cod==6)
                  {
                     sub_mode=0;
                  }
               }
            }
            
              break;
            
      case 4:       // Fuel max
              pointer_clear();
              print_string_5x8(0,main_dark_mode,"->");
              main_text();
            if (cod==5)
            {
               cod=0;                               // Сразу обнулим код нажатия кнопки
               screen_clear();                      // Очистим экран
               sub_mode=1;
               
               while(sub_mode)
               {
                  cod=buttons();
                  print_string_5x8(16,2,"PRESS BUTTON ");
                  print_string_5x8(16,3,"FOR MEMORY");
                  print_string_5x8(16,4,"ENTRIES MAX");
                  screen_update();
                  if (cod==6)
                  {
                     sub_mode=0;
                  }
               }
            }
              break;            
             
                     
   }
}


void correction(uint8_t size,uint16_t eep_number, uint8_t *par)
{   
   
   uint8_t a=51; // Параметр начала строки. Магическое число. С этой позиции курсора начинаем вывод
   
         for (uint8_t i; i<size; i++)
         {
            
            print_MediumNumbers(a,6,par[i]%10 + '0'); // Выводим все разряды корректируемой величины
            a+=12;
            
         }
         
         if (cod==5) // при двойном нажатии прыгаем на следующую циферку, которую нам необходимо изменить и подсвечиваем
                    // ее инверсией
         {
            b++; // при каждом двойном нажатии кнопки инкрементируем переменную
            cod=0; //Обнуляем код нажатия для следующего скана
            if(b==size) b=0; // В зависимости от переданного в функцию количества разрядов корректируемой величины
                             // инкрементируем разряды
                        
            pr_var=par[b]; // Читаем в переменную содержание элемента массива
         }
         
         print_invert_MediumNumbers(51+(b*12),6,par[b]%10 + '0'); // Инвертируем картинку редактируемого разряда
         
         if(cod==3) // Если редактируем
         {
            pr_var++; // Если нажали кнопку, увеличиваем значение переменной на +1
            if(pr_var>9) pr_var=0;
            
            cod=0; // Обнуляем код нажатия кнопки
            par[b]=pr_var; // Записываем это значение в выбранный элемент массива
         }
   }

Re: Измерение скорости автомобиля по штатному датчику

Вс сен 17, 2023 10:52:08

Попробовал я buttons() в симуляторе
IMHO она нормально не будет работать с двойным кликом. Только если аппаратный антидребезг сделать.
Кроме того, "флажки" не инициализируются, поэтому первый клик часто глючный.

Вот эта библиотека
https://github.com/TanPitch/ButtonKing
В симуляторе работает значительно лучше. Хотя на физической кнопке (типа Jog Dial) могут быть нюансы.

И ещё.
button1_timer = millis;
Эта операция не атомарная. Если прерывание с инкрементом millis сработает внутри, то может оказаться, что часть байтов этой переменной будет от старого состояния millis, часть - от нового. Это касается всех операций с millis.

Re: Измерение скорости автомобиля по штатному датчику

Вс сен 17, 2023 16:46:04

Спасибо за библиотеку. Правда я не силен в с++, но попробую портировать.
Ответить