K-CAN Проект

Чип тунинг, Standalone и piggyback електроники.

Модератор: bum_bum

старши ентусиаст
Аватар
Мнения: 1857
Регистриран на: 20.10.2010
Местоположение: София
Пол: Мъж
Кара: BigBlockV8 и чат-пат SmallBlockV8
Мечтае да кара: бангия с предно
Детайли за колата: ;)
Big: Hemi 370 cu. in.
Small: S62B50 с жокери

Re: K-CAN Проект

Мнение от Nickelback » 26 Юли 2017, 21:51

Супер, има раздвижване :yes: Аз пак да пусна една муха :) Така и така ще ползваш RPi (а може и нещо по-мощно :)), защо не закачиш и една камерка за него и не си направиш gesture control с OpenCV (има порт за Python :ok: ) поне да си регулираш музиката и да си сменяш песните с ръкомахане. Може и някакъв vehicle customization (автоматично регулиране на седалката, да речем) като ти разпознае лицето. Ще е яко :yes:
Изображение Изображение

"За тЕя пари има Е-шеесе" - форумна пословица.
Лето две и седемнаесто.

Потребител
Аватар
Мнения: 31
Регистриран на: 5.04.2016
Пол: Мъж
Кара: BMW 120d e87
Детайли за колата: BMW 120d e87 163hp

Re: K-CAN Проект

Мнение от shadowx » 27 Юли 2017, 2:30

Мислех го, но реално gesture hat има за 30-40лв https://www.adafruit.com/product/2325 :) не е нужно да се занимаваш с OpenCV даже ... (аз имам малко опит попринцип ... боене на коли... четене на номера :mhihi: )
(Не официално работя и над едно друго проектче, което основно разчита на OpenCV :D ...но то няма общо с колата... там е социален проект.)

старши ентусиаст
Аватар
Мнения: 1857
Регистриран на: 20.10.2010
Местоположение: София
Пол: Мъж
Кара: BigBlockV8 и чат-пат SmallBlockV8
Мечтае да кара: бангия с предно
Детайли за колата: ;)
Big: Hemi 370 cu. in.
Small: S62B50 с жокери

Re: K-CAN Проект

Мнение от Nickelback » 27 Юли 2017, 8:04

shadowx написа:Мислех го, но реално gesture hat има за 30-40лв https://www.adafruit.com/product/2325 :) не е нужно да се занимаваш с OpenCV даже ... (аз имам малко опит попринцип ... боене на коли... четене на номера :mhihi: )
(Не официално работя и над едно друго проектче, което основно разчита на OpenCV :D ...но то няма общо с колата... там е социален проект.)

"Senses from up to 5cm away" :)

Не е същото като с камера, сещаш се... :)

OpenCV-то на PC ли си го пробвал или пак на някакъв борд?
Изображение Изображение

"За тЕя пари има Е-шеесе" - форумна пословица.
Лето две и седемнаесто.

Потребител
Аватар
Мнения: 31
Регистриран на: 5.04.2016
Пол: Мъж
Кара: BMW 120d e87
Детайли за колата: BMW 120d e87 163hp

Re: K-CAN Проект

Мнение от shadowx » 27 Юли 2017, 8:39

Nickelback написа:"Senses from up to 5cm away" :)

Не е същото като с камера, сещаш се... :)

Да...и по-ограничено от към жестове... но пък поставено на мястото на зад скорностния лост , 5см биха били достатъчни, защото ще е удобно....
М/у другото за OpenCV-то ...може и face recodnicion за разрешаване на запалването... но трябва да пускаш RPi-то при отключване от дистанционното например за да може да е заредило малко след като си в колата.
Реално с този дизаин arudino + rpi - the sky is the limit :)

Nickelback написа:OpenCV-то на PC ли си го пробвал или пак на някакъв борд?

На x86/x86_64 и разни ARM-та :)

старши ентусиаст
Аватар
Мнения: 1857
Регистриран на: 20.10.2010
Местоположение: София
Пол: Мъж
Кара: BigBlockV8 и чат-пат SmallBlockV8
Мечтае да кара: бангия с предно
Детайли за колата: ;)
Big: Hemi 370 cu. in.
Small: S62B50 с жокери

Re: K-CAN Проект

Мнение от Nickelback » 27 Юли 2017, 18:30

Щеше да е яко, ако расберито си имаше нормален power management, за да го сложиш в low power mode, а не го чакаш да буутва всеки път. Аз за това не го харесвам за енергоефективни проекти.
Face recognition-а е яко, ама още не съм си играл да видя доколко е надежден и как/колко трябва да се обучава за конкретно лице или набор от лица... Ако си пробвал - сподели :yes:
На какви ARM-ове точно си пускал OpenCV, че си е драма на повечето...?
Изображение Изображение

"За тЕя пари има Е-шеесе" - форумна пословица.
Лето две и седемнаесто.

Потребител
Аватар
Мнения: 31
Регистриран на: 5.04.2016
Пол: Мъж
Кара: BMW 120d e87
Детайли за колата: BMW 120d e87 163hp

Re: K-CAN Проект

Мнение от shadowx » 27 Юли 2017, 19:19

Nickelback написа:Щеше да е яко, ако расберито си имаше нормален power management, за да го сложиш в low power mode, а не го чакаш да буутва всеки път. Аз за това не го харесвам за енергоефективни проекти.
Face recognition-а е яко, ама още не съм си играл да видя доколко е надежден и как/колко трябва да се обучава за конкретно лице или набор от лица... Ако си пробвал - сподели :yes:
На какви ARM-ове точно си пускал OpenCV, че си е драма на повечето...?

Мдам ... PM няма на ARMтата :( ...нищо, само с едно бързо махане на неща от init скриптовете и имам стартирано mpd на 19тата секунда... и като го направя
* keyfob_lock_event -> send shutdown (kill the relay 10-15s later).
* keyfob_unlock_event -> power up RPi
Реално, докато влезна в колата, сложа ключа, въведа "кода", сложа колана и вече ще е активен 1000%.
Та и без PM изглежда напълно изпълнимо в разумни граници.

Относно Face recognition.... ами... като с всичко друго при OpenCV....ако си го "обучил" добре, се справя доста добре....that said, ако се прави с една камера (т.е. нямаш 3д) ... снимки си го бъркат лесно :mhihi:
Но, разбираемо.... Face recognition е реално няколко стъпков процес ...1во търсиш лице в кадъра... така остава по-малък таргет за обработване... после в този "таргет" , търсиш очи, нос, уста... ..пак същия филм...разделяш... на тях пък, почваш да проверяваш пропорции .. (Face recognition си е това)... но като имаш 2д образ (т.е. 1 камера само) ... 2д репрезентация (т.е. снимка) отговаря напълно на исканото ... препдолагам OpenCV предлага решение на този пороблем по алтернативен начин, не съм влизал толкова на дълбоко :roll:

RPi1B с лек клок (100-200Mhz) се справаше прилично да обработва номера в реално време ... но беше направено със висока резолюция и нисък фрейм рейт ...(и хубава IP камера да подчертая) ..та финта беше така ...камерата предлагаше паралелно и висока и ниска резолюция ... взимаш един фрейм и от 2те... за да откриеш къде има регистрационнен номер, не ти трябва много голяма рез. ...та търсиш в малката снимка (то пак е двоен процес..1во откриваш кола, после търсиш в нея регистрация) ..та като ги откриеш като кординати , смяташ при голямата къде биха се падали и четеш от нея само парчето със регистрационния номер :mhihi: :lalala: :smoke:
brain kung-fu е OpenCV-то.... само въображението ограничава какво може да направи човек с него :D

старши ентусиаст
Аватар
Мнения: 1857
Регистриран на: 20.10.2010
Местоположение: София
Пол: Мъж
Кара: BigBlockV8 и чат-пат SmallBlockV8
Мечтае да кара: бангия с предно
Детайли за колата: ;)
Big: Hemi 370 cu. in.
Small: S62B50 с жокери

Re: K-CAN Проект

Мнение от Nickelback » 28 Юли 2017, 9:34

О напротив, ARM-базираните SoC-ове си имат прекрасни възможности за истински power management :)
Гейтване на клоци, спиране на захранването на отделни машини, self retention на RAM-a и т.н. както си му е реда.
А аз говоря конкретно за RPi, при което:
1. Няма "истински" PMIC чип на борда
2. Някои от драйверите използвани от RPi нямат пълноценна поддръжка на какъвто и да било power moding - например VC4 драйвера, който основно Broadcom си го бутат там.

Та така... не са "ARM-овете" виновни :)

За някои фийчъри не е приятно 20 секунди време на реакция на системата - основно remote команди. Ти поне не планираш такива, доколкото разбирам.

Иначе ARM рилийзнаха ARM Compute Library (ползва NEON инструкциите и Mali GPU-то).
Като скорост очаквам да се справя по-добре от OpenCV вървящо върху ARM. Предстои да си играя с това и ще споделя :)
Изображение Изображение

"За тЕя пари има Е-шеесе" - форумна пословица.
Лето две и седемнаесто.

Потребител
Аватар
Мнения: 31
Регистриран на: 5.04.2016
Пол: Мъж
Кара: BMW 120d e87
Детайли за колата: BMW 120d e87 163hp

Re: K-CAN Проект

Мнение от shadowx » 28 Юли 2017, 18:03

Nickelback написа:О напротив, ARM-базираните SoC-ове си имат прекрасни възможности за истински power management :)
Гейтване на клоци, спиране на захранването на отделни машини, self retention на RAM-a и т.н. както си му е реда.
А аз говоря конкретно за RPi, при което:
1. Няма "истински" PMIC чип на борда
2. Някои от драйверите използвани от RPi нямат пълноценна поддръжка на какъвто и да било power moding - например VC4 драйвера, който основно Broadcom си го бутат там.

Та така... не са "ARM-овете" виновни :)

За някои фийчъри не е приятно 20 секунди време на реакция на системата - основно remote команди. Ти поне не планираш такива, доколкото разбирам.

Иначе ARM рилийзнаха ARM Compute Library (ползва NEON инструкциите и Mali GPU-то).
Като скорост очаквам да се справя по-добре от OpenCV вървящо върху ARM. Предстои да си играя с това и ще споделя :)

GPU ако смята за OpenCV нещата, ще е адски бързо..то си е баш за такъв тип процесори работа :) Очаквам да споделиш като имаш нещо по въпроса, ще ми е интересно да разгледам :)

Относно PM ...и да и не..първо да кажа,че най-вече говоря за процесорите които се използват в OPi,RPi,BPi и подобните.... определено, самия хардуер има доста по приличен PM от това което е "достъпно" заради недописани driver-и.... that said ...ARM си е дървено (аз гледам от гледната точка на човек който е израснал с x86 малко или много) ...та очаквам от хардуера в днешно време да мога да изполвам ядрата с динамични честоти , необвързани едно с друго (т.е. да мога да си set-на cpu0 на една честота , cpu1 на друга , cpu2 на 3та)
Също така, мисля,че е донякъде нормално за подобен тип устройство да подръжа suspend to memory и да преминава в low power state ... поправи ме ако греша , но това по дизайн е невъззможно на RPi 1,2,3 ....
За RPi1 е обяснимо...там процесора беше правен за друго ....излезна ,че е дефектен и просто се чудеха кво да го правят и се роди RPi1 ...но за другите....

Иначе има и такива с доста приличен PM... TI имаха cortex-a8 много добри ... от друга страна и пазара малко е виновен ...защото смешния android с неговия малумен PM (имам огромен проблем с PM концепцията им на тези хора) не ги ...нека го наерчем "води" в правилната посока.

p.s. ето нещо да се посмееш малко https://vuldb.com/?id.101724

Потребител
Аватар
Мнения: 31
Регистриран на: 5.04.2016
Пол: Мъж
Кара: BMW 120d e87
Детайли за колата: BMW 120d e87 163hp

Re: K-CAN Проект

Мнение от shadowx » 01 Авг 2017, 23:22

Това даже не е alfa .... все още е само POC, но field tested и изглежда добре.
Някой от нещата връщат грешни данни (среден разход на л/100км например... ), други има частични (волана... отчита градусите само при въртене наляво) и още няколко такива...
Но ...в тази жега, не ми се седи дълго в колата да дебъгвам...а ако ида в подземен гараж на мол с лаптоп и кабели излизащи от таблото .... :mhihi: мдам...

Та... аз на C не мога да пиша ... та, кода е грозен и гаден, но що-годе работещ...та се извинявам предварително , ако някой го заболят очите докато го чете :paranoid:
Иначе освен очеизвадното изписване на статуси през serial port-а, има и това за което говорих с контрола на релето на горивната помпа и кода за "отключване/активация" посредством код /комбинация от копчета/ на волана.

unlock_code[] е array с "паролата"
Ако променяте дължината , променете и PASS_LEN (иначе ще стане една боза с паметта... щото аз малко memcpy-вам тук-там :winky: )
Има описана "защита" от рестарт по-време на работа..т.е. няма да ви изключи горивната помпа ако се рестартира по време на работа на двигателя.
Ако обаче настъпи рестарт когато колата е загасена, ще приеме,че е в lockdown режим и при наличие на ключ , ще започне да активира релето до въвеждане на код.
Иначе , ако няма рестарт, lockdown се активира само след заключване от дистанционното.
Като цяло "lockdown" статуса не е лоша идея да се прехвърли във EEPROM-а на Arduino-то ..също така може и "кода" да се запише там...

anyway , всякакъв feedback е полезен. :) :P

Код: Избери целия код
/*
    carpino.ino - BMW K-CAN Traffic Parsing
    Copyright (C) 2017 Georgi Kolev <georgi.kolev gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Credits should mostly go to Trevor Cook <http://loopybunny.co.uk/>
    For decoding the K-CAN traffic.
*/

#include "Canbus.h"
#include "defaults.h"
#include "global.h"
#include "mcp2515.h"
#include "mcp2515_defs.h"
#include <PrintEx.h>

#define SERIAL_SPEED  250000
#define RPI_OFFTIME   90000
#define CANSPEED_100  9
#define PASS_LEN      6

#define BUZZER_PIN    8
#define OPI_PIN       7
#define FPR_PIN       6

#define B_VOICE     0
#define B_PHONE     1
#define B_VOLUP     2
#define B_TUNEUP    3
#define B_VOLDOWN   4
#define B_CHANGER   5
#define B_AIRFLOW   6
#define B_TUNEDOWN  7


int tmpint, tmpint2;
int stack_array[PASS_LEN];
unsigned long rpi_deadline;
unsigned long bt_voice, bt_airflow, bt_tuneup, bt_voldown;
unsigned long bt_phone, bt_changer, bt_volup, bt_tunedown;
const int unlock_code[PASS_LEN] = {
  B_VOICE, B_CHANGER, B_PHONE, B_VOICE, B_CHANGER, B_PHONE };
const unsigned long btn_threshold = 500; // Threshold long press (ms)

PrintEx serial = Serial;
// This will add the printf() method to "Serial"
//PrintExWrap<typeof(Serial)> &__Serial = PrintEx::wrap(Serial);
//#define Serial __Serial

struct CarValues {
  int swheel;
  int coolant;
  int freemem;
  byte fuel;
  byte fan_speed;
  long odometer;
  float speed;
  float avr_lkm;
  float avr_kmh;
  float in_temp;
  float ext_temp;
  float left_temp;
  float right_temp;
  char datetime[20];
  unsigned int rpm;
  unsigned int range;
  unsigned char throttle;
  unsigned char fl_window;
  unsigned char fr_window;
  unsigned char rl_window;
  unsigned char rr_window;
};

struct CarStatus {
  union {
    unsigned char value[5];
    struct {
      unsigned key:1;
      unsigned init:1;
      unsigned locked:1;
      unsigned engine:1;
      unsigned reverse:1;
      unsigned lockdown:1;
      unsigned handbrake:1;
      unsigned fuelrelay:1; // 8
      // Door status open/lock
      unsigned fl_door:1;
      unsigned fr_door:1;
      unsigned rl_door:1;
      unsigned rr_door:1;
      unsigned fl_lock:1;
      unsigned fr_lock:1;
      unsigned rl_lock:1;
      unsigned rr_lock:1; // 16
      // Hood status open
      unsigned hood:1;
      // Boot status open/lock
      unsigned boot:1;
      unsigned boot_lock:1; // TBD
      // Low/Main/High Beams
      unsigned low_beam:1;
      unsigned main_beam:1;
      unsigned high_beam:1; // TBD
      // Fog lights
      unsigned rear_fog:1;
      unsigned front_fog:1; // 24
      // Others
      unsigned term15:1;
      unsigned term30:1;
      unsigned clutch:1;
      unsigned brakes:1;
      unsigned demister:1;
      unsigned door_alarm:1;
      unsigned aircondition:1;
      unsigned airconditionmax:1; // 32
      unsigned recirculate:1;
      unsigned recirculateauto:1;
      unsigned rpi;
      unsigned hazard_lights;
      unsigned left_turnsignal;
      unsigned right_turnsignal;
    };
  };
} __attribute__((packed));

struct CarStatus car;
struct CarValues carv;


// Check free memory
int freeRam() {
  int v;
  extern int __heap_start, *__brkval;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

// RPi Power Relay Functions
void rpi_on()  { digitalWrite(FPR_PIN, 1); car.rpi = 1; }
void rpi_off() { digitalWrite(FPR_PIN, 0); rpi_deadline = 0; car.rpi = 0; }
void rpi_shutdown() { rpi_deadline = millis() + RPI_OFFTIME; }

// Fuel Relay Control Function
void fpr_control(boolean s) {
  car.fuelrelay = scheck("fuel_relay", s, car.fuelrelay);
  digitalWrite(FPR_PIN, car.fuelrelay);
  memset(stack_array, 0, (sizeof(int) * PASS_LEN));
}

// Add to button stack
void button_stack(int p) {
  if (car.init && car.lockdown) {
    stack_push(p);
    if (arrcmp(unlock_code, stack_array, PASS_LEN)) {
      Serial.println("auth=true");
      fpr_control(0);
      car.lockdown = 0;
      tone(BUZZER_PIN, 6000, 100);
    } else { // DEBUG ONLY
      Serial.print("arrcmp(");
      for (int n=0; n<PASS_LEN; n++)
        Serial.print(stack_array[n]);
      Serial.print(", ");
      for (int n=0; n<PASS_LEN; n++)
        Serial.print(unlock_code[n]);
      Serial.println(")");
    }
  }
}

// LIFO Stack Push
void stack_push(int p) {
  int temp_array[PASS_LEN-1];
  memcpy(temp_array, stack_array, (sizeof(int) * (PASS_LEN-1)));
  memcpy(&stack_array[1], temp_array, (sizeof(int) * (PASS_LEN-1)));
  stack_array[0] = p;
}

// Compare arrays
boolean arrcmp(int a[], int b[], int n) {
  int i = 0;
  boolean c = true;
  while(i < n && c) {
    c = a[i] == b[i];
    i++;
  }
  return c;
}

// Short/Long Button Press
int long_press(unsigned long ptime) {
  if ((millis() - ptime) > btn_threshold)
    return 2;
  return 1;
}

// int/status check
int scheck(char pstr[], unsigned nval, unsigned cval) {
  if (cval != nval) pprint(pstr, nval, 0);
  return nval;
}

// Float value check
int vcheck(char pstr[], float nval, float cval) {
  if (cval != nval) pprint(pstr, 0, nval);
  return nval;
}

// Custom print function
void pprint(char pstr[], unsigned pint,float pdig) {
  if (pdig) serial.printf("%s=%4.2f\n", pstr, pdig);
  else serial.printf("%s=%u\n", pstr, pint);
  Serial.flush();
}

// Get top/bottom (high/low) 4 bits
int low_bits(int b)  { return b & 0xF; }
int high_bits(int b) { return (b>>4) & 0xF; }


// Initial Setup
void setup() {
  car.init = 0;
  // Setup serial port
  Serial.begin(SERIAL_SPEED);
  // Initizalize
  Serial.print("Init...");
  // PINs
  pinMode(OPI_PIN, OUTPUT);
  pinMode(FPR_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  tone(BUZZER_PIN, 6000, 100);
  // Initialize CAN Bus
  if(Canbus.init(CANSPEED_100))
    Serial.println("OK");
  else
    Serial.println("FAIL");
  carv.freemem = scheck("free_memory", freeRam(), carv.freemem);
}

// Main Loop
void loop(){
 
  tCAN message;

  // Fuel relay lock/unlock
  if (car.init) {
    if ((!car.key) && car.fuelrelay) fpr_control(0);
    if (car.key && car.lockdown && (!car.fuelrelay)) fpr_control(1);
  }
  // RPi on/off relay
  if ((!car.rpi) && car.engine) rpi_on();
  if (rpi_deadline && car.rpi && (millis() > rpi_deadline)) rpi_off();


  // check for message from the can bus
  if (mcp2515_check_message()) {
    if (mcp2515_get_message(&message)) {

      switch (message.id) {
        case 0x1D6: // Steering wheel buttons
          // Volume UP
          if (bitRead(message.data[0], 3) && (!bt_volup)) {
            bt_volup = millis();
          } else if ((!bitRead(message.data[0], 3)) && bt_volup) {
            pprint("bt_volup", long_press(bt_volup), 0);
            button_stack(B_VOLUP);
            bt_volup = 0;
          }
          if (bitRead(message.data[0], 2) && (!bt_voldown)) {
            bt_voldown = millis();
          } else if ((!bitRead(message.data[0], 2)) && bt_voldown) {
            pprint("bt_voldown", long_press(bt_voldown), 0);
            button_stack(B_VOLDOWN);
            bt_voldown = 0;
          }
          if (bitRead(message.data[1], 0) && (!bt_voice)) {
            bt_voice = millis();
          } else if ((!bitRead(message.data[1], 0)) && bt_voice) {
            pprint("bt_voice", long_press(bt_voice), 0);
            button_stack(B_VOICE);
            bt_voice = 0;
          }
          if (bitRead(message.data[0], 0) && (!bt_phone)) {
            bt_phone = millis();
          } else if ((!bitRead(message.data[0], 0)) && bt_phone) {
            pprint("bt_phone", long_press(bt_phone), 0);
            button_stack(B_PHONE);
            bt_phone = 0;
          }
          if (bitRead(message.data[1], 6) && (!bt_changer)) {
            bt_changer = millis();
          } else if ((!bitRead(message.data[1], 6)) && bt_changer) {
            pprint("bt_changer", long_press(bt_changer), 0);
            button_stack(B_CHANGER);
            bt_changer = 0;
          }
          if (bitRead(message.data[1], 4) && (!bt_airflow)) {
            bt_airflow = millis();
          } else if ((!bitRead(message.data[1], 4)) && bt_airflow) {
            pprint("bt_airflow", long_press(bt_airflow), 0);
            button_stack(B_AIRFLOW);
            bt_airflow = 0;
          }
          if (bitRead(message.data[0], 5) && (!bt_tuneup)) {
            bt_airflow = millis();
          } else if ((!bitRead(message.data[0], 5)) && bt_tuneup) {
            pprint("bt_tuneup", long_press(bt_tuneup), 0);
            button_stack(B_TUNEUP);
            bt_tuneup = 0;
          }
          if (bitRead(message.data[0], 4) && (!bt_tunedown)) {
            bt_airflow = millis();
          } else if ((!bitRead(message.data[0], 4)) && bt_tunedown) {
            pprint("bt_tunedown", long_press(bt_tunedown), 0);
            button_stack(B_TUNEDOWN);
            bt_tunedown = 0;
          }
          break;
        case 0x23A: // Keyfob
          if (bitRead(message.data[2], 2) && (!car.locked)) {
            rpi_shutdown();
            car.locked = 1;
            car.lockdown = 1;
            Serial.println("keyfob=lock");
          }
          if (bitRead(message.data[2], 0) && car.locked) {
            rpi_on();
            car.locked = 0;
            Serial.println("keyfob=unlock");
          }
          if (bitRead(message.data[3], 4) && car.boot_lock) {
            car.boot_lock = 0;
            Serial.println("keyfob=boot");
          }
          break;
        case 0x3B0: // Rerverse gear
          car.reverse = scheck("reverse", bitRead(message.data[0], 7), car.reverse);
          break;
        case 0x32E: // Internal Temperature
          carv.in_temp = vcheck("in_temp", ((message.data[3] / 10) + 6), carv.in_temp);
          break;
        case 0x1D0: // Coolant
          carv.coolant = vcheck("coolant", (message.data[0] - 48), carv.coolant);
          break;
        case 0xAA: // RPM, Throttle
          carv.rpm = scheck("rpm",
                  (((message.data[5] * 0x100) + message.data[4]) / 4), carv.rpm);
          carv.throttle = scheck("throttle",
                  (((message.data[3] * 0x100) + message.data[2]) / 256), carv.throttle);
          if ((carv.rpm > 0) && (!car.engine))
            car.engine = scheck("engine", 1, car.engine);
          else if ((!carv.rpm) && car.engine)
            car.engine = scheck("engine", 0, car.engine);
          // We should this case if the board restarts while the car is running
          // It will be bad if we shut it down.
          if (!car.init) {
            car.init = 1;
            if (carv.rpm) {
              car.lockdown = 0; Serial.println("unlock=forced");
            } else {
              car.lockdown = 1; Serial.println("lockdown=on");
            }
          }
          break;
        case 0x1B4: // Speed, Handbreak
          carv.speed = vcheck("speed",
              (((((message.data[1] - 0xC0) * 256) + message.data[0]) / 16) * 1.6), carv.speed);
          //car.handbrake = scheck("handbrake", bitRead(message.data[5], 1), bitRead(car.handbrake,0));
          break;
        case 0x330: // Odmeter & Range are also in this ID
          //carv.range = ("range", (((message.data[7] * 256) + message.data[6]) / 16), carv.range);
          carv.fuel = scheck("fuel", message.data[3], carv.fuel);
          carv.odometer = ((message.data[2] * 0x10000) + (message.data[1] * 0x100) + message.data[0]);
          Serial.print("odometer=");
          Serial.println(carv.odometer);
          break;
        case 0x34F: // Handbreak
          car.handbrake = scheck("handbrake", bitRead(message.data[0], 6), car.handbrake);
          break;
        //case 0x2CA: // Outside Temperature (Missing on e87. Check for ext_temp.)
          //carv.out_temp = vcheck("out_temp", ((message.data[0] - 80) / 2.0), carv.out_temp);
          //break;
        case 0x130: // Engine & Key Status
          car.key = scheck("key", bitRead(message.data[1], 6), car.key);
          car.term15 = scheck("term15", bitRead(message.data[0], 2), car.term15);
          car.clutch = scheck("clutch", bitRead(message.data[2], 6), car.clutch);
          if (!car.init) {
            car.init = 1;
            if (!car.key) {
              car.lockdown = 1;
              Serial.println("lockdown=nokey");
            }
          }
          break;
        case 0x24B: // Door Alarms
          if (message.data[0]) car.door_alarm = scheck("door_alarms", 1, car.door_alarm);
          else car.door_alarm = scheck("door_alarms", 0, car.door_alarm);
          break;
        case 0x21A: // Lights
          car.brakes = scheck("brakes", bitRead(message.data[0], 7), car.brakes);
          car.rear_fog = scheck("rear_fog", bitRead(message.data[0], 6), car.rear_fog);
          car.low_beam = scheck("low_beam", bitRead(message.data[0], 2), car.low_beam);
          car.front_fog = scheck("front_fog", bitRead(message.data[0], 5), car.front_fog);
          car.main_beam = scheck("main_beam", bitRead(message.data[0], 0), car.main_beam);
          //car.interior_light = scheck("interior_light",
          //          bitRead(message.data[0], 6), car.interior_light);
          break;
        case 0x246: // Rear demister
          car.demister = scheck("demister", bitRead(message.data[0], 1), car.demister);
          break;
        case 0x2E6: // Left clima temp & Fan speed
          carv.left_temp = vcheck("left_temp", (message.data[7] / 2.0), carv.left_temp);
          carv.fan_speed = scheck("fan_speed", message.data[5], carv.fan_speed);
          break;
        case 0x2EA: // Right clima temp
          carv.right_temp = vcheck("right_temp", (message.data[7] / 2.0), carv.right_temp);
          break;
        case 0x366: // External Temp, Range
          carv.freemem = scheck("free_memory", freeRam(), carv.freemem);
          carv.range = scheck("range",
                ((((message.data[2] * 256) + message.data[1]) / 16)), carv.range);
          carv.ext_temp = vcheck("ext_temp", ((message.data[0] - 80) / 2.0), carv.ext_temp);
          break;
        case 0x2FC: // Door & Boot Status
          car.fl_door = scheck("fl_door", bitRead(message.data[1], 0), car.fl_door);
          car.fr_door = scheck("fr_door", bitRead(message.data[1], 3), car.fr_door);
          car.rl_door = scheck("rl_door", bitRead(message.data[1], 5), car.rl_door);
          car.rr_door = scheck("rr_door", bitRead(message.data[1], 7), car.rr_door);
          car.boot = scheck("boot", bitRead(message.data[2], 0), car.boot);
          break;
        case 0x3B6: // Front left window
          carv.fl_window = scheck("fl_window", message.data[0], carv.fl_window);
          break;
        case 0x3B7: // Rear left window
          carv.rl_window = scheck("rl_window", message.data[0], carv.rl_window);
          break;
        case 0xC8: // Steering wheel angle (FIX THIS!)
          tmpint = (((message.data[1] * 0xFF) + message.data[0]) / 23);
          tmpint2 = ((((message.data[1] * 0xFF) + message.data[0]) - 0xFFFF) / 23);
          if (tmpint < 360 && tmpint > -1)
            carv.swheel = scheck("steering_wheel", tmpint, carv.swheel);
          if (tmpint2 < -360 && 1 > tmpint2)
            carv.swheel = scheck("steering_wheel", tmpint2, carv.swheel);
          break;
        case 0x3B8: // Front reft window
          carv.fr_window = scheck("fr_window", message.data[0], carv.fr_window);
          break;
        case 0x3B9: // Rear right window
          carv.rr_window = scheck("rr_window", message.data[0], carv.rr_window);
          break;
        case 0x1F6: // turn signal/Hazzard Lights (testing)
          if (message.data[0] == 0x91) {
            car.left_turnsignal = scheck("left_turnsignal", 1, car.left_turnsignal);
          } else if (message.data[0] == 0xA1) {
            car.right_turnsignal = scheck("right_turnsignal", 1, car.right_turnsignal);
          } else if (message.data[0] == 0xB1) {
            car.hazard_lights = scheck("hazard_lights", 1, car.hazard_lights);
          } else {
            car.left_turnsignal = scheck("left_turnsignal", 0, car.left_turnsignal);
            car.right_turnsignal = scheck("right_turnsignal", 0, car.right_turnsignal);
            car.hazard_lights = scheck("hazard_lights", 0, car.hazard_lights);
          }
          break;
        //case 0xF2:  // Boot Lock (Missing in e87?)
        case 0x1EE: // Indicator Stalk position (testing)
          car.high_beam = scheck("high_beam", bitRead(message.data[0], 4), car.high_beam);
          car.left_turnsignal = scheck("left_turnsignal", bitRead(message.data[0], 3), car.left_turnsignal);
          car.right_turnsignal = scheck("right_turnsignal", bitRead(message.data[0], 1), car.right_turnsignal);
          if (message.data[0] == 0x01) Serial.println("right_blink=1");
          else if (message.data[0] == 0x04) Serial.println("left_blink=1");
          else if (message.data[0] == 0x20) Serial.println("highbeam_flash=1");
          break;
        //case 0x252: // Windscreen Wiper Status (TBD)
        //case 0x2A6: // Windscreen Wiper Controls (TBD)
        //case 0x349: // Left/Right Fuel Sensor (TBD)
        //case 0x328: // Battery Reset, Production date (TBD)
        case 0x362: // Average KM/h & l/100km (l/km wrong?)
          Serial.print(" 0x362 ");
          Serial.print(message.data[0], HEX); Serial.print(" ");
          Serial.print(message.data[1], HEX); Serial.print(" ");
          Serial.println(message.data[2], HEX);
          carv.avr_lkm = vcheck("avr_lkm", (235.214 *
              ((message.data[2] + (high_bits(message.data[1]) * 0x100)) / 10)), carv.avr_lkm);
//              ((message.data[2] * 0x10) + high_bits(message.data[1])) / 10), carv.avr_lkm);
          carv.avr_kmh = vcheck("avr_kmh",
              ((message.data[0] + (low_bits(message.data[1]) * 0x100)) / 10), carv.avr_kmh);
          break;
        case 0x380: // VIN
          Serial.print("vin=");
          for (int u=0; u < message.header.length; u++) {
            char c = (char) message.data[u];
            Serial.print(c);
          }
          Serial.println();
          break;
        case 0x2F8: // Time & Date
          Serial.print("datetime=");
          sprintf(carv.datetime, "%02d:%02d:%02d %02d/%02d/%d",
                  message.data[0], message.data[1], message.data[2],
                  message.data[3], high_bits(message.data[4]),
                  ((message.data[6] * 0x100) + message.data[5]));
          carv.datetime[20] = '\0';
          Serial.println(carv.datetime);
          break;
        case 0x242: // AC Status, Air Recirculation
          car.recirculate = scheck("recirculate",
                bitRead(message.data[0], 5), car.recirculate);
          car.aircondition = scheck("aircondition",
                bitRead(message.data[0], 0), car.aircondition);
          car.airconditionmax = scheck("ac_max",
                bitRead(message.data[0], 2), car.airconditionmax);
          car.recirculateauto = scheck("recirculate_auto",
                bitRead(message.data[0], 4), car.recirculateauto);
          break;
        case 0x26E: // Testing
          if (message.data[1])
            car.term30 = scheck("term30", 1, car.term30);
          else
            car.term30 = scheck("term30", 0, car.term30);
          break;
        default: // When done with the known traffic we should start printing what is left
          break;
      }
    }
  }
}

п.с.: Аз наистина не мога да пиша C (като цяло не мога да програмирам...но и не ми е работа) ..обаче Arudino IDE девелопърите къртят мивки...
#define boolean uint8_t :kuku:
У-во с 2kb памет и да пляскаш по 8бита за нещо което е 1 бит.... :censored:
Но за сега кода използва разумно количество памет.
Sketch uses 12,574 bytes (38%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,197 bytes (58%) of dynamic memory, leaving 851 bytes for local variables. Maximum is 2,048 bytes.

кандидат ентусиаст
Аватар
Мнения: 75
Регистриран на: 17.01.2020
Местоположение: Пловдив
Пол: Мъж
Кара: F10 LCI 530xD
Мечтае да кара: Самолет
Детайли за колата: Убава йе. Има 4 колелета.

Re: K-CAN Проект

Мнение от mrwrong » 14 Юли 2023, 18:04

Малко да посъживя темата. Някой успял ли е да изправи по K-can шината някой код който да бъде изпълнен от колата. Имам предвид примерно да накара да мигат мигачите. За сега успявам само да слушам командите по шината , но не успявам да изпълня команда. Ще се радвам ако някой сподели опит.

Предишна

Назад към Електроника

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани

Последни теми
Facebook