Fórum témák
- • Arduino
- • Nagyfeszültségű tápegység
- • Kondenzátor
- • Szünetmentes táp javítása, élesztése
- • Felajánlás, azaz ingyen elvihető
- • Akkumulátor töltő
- • Erősítő építése elejétől a végéig
- • Műhelyünk felszerelése, szerszámai
- • Mikrohullámú sütő javítás, magnetron csere, stb.
- • Klíma szervizelés, javítás
- • Elfogadnám, ha ingyen elvihető
- • Kombikazán működési hiba
- • Erősítő mindig és mindig
- • Számítógép hiba, de mi a probléma?
- • Digitális óra
- • Függvénygenerátor építése
- • SMD, mi a típusa?
- • Elektromos távirányítós kapunyitó
- • Hibrid erősítő
- • Hűtőgép probléma
- • Suzuki Swift elektronika
- • Videomagnó problémák
- • Általános antennás kérdések, válaszok
- • Érdekességek
- • STK erősítők javítások
- • DC-DC konverter max. kapacitív terhelése
- • Háromfázisú aggregátor
- • Audiofil, High End Audio
- • Alternativ HE találkozó(k)
- • Központi fűtés (vezérlés)
- • IMI villanymotor
- • Borhűtő vezérlő panel
- • Androidos okos telefonok
- • Klíma beszerelése, fűtés-hűtés házilag
- • Súlymérés
- • Dobozolási technikák, műszerdobozok
- • Laptop javítás, tuning
- • Varrógép elektronika
- • Mosógép vezérlők és általános problémáik
- • Analóg oszcilloszkóp javítása
- • Boombox javítás
- • Videoton EA-7386-s erösítő
- • Digitális mérleg
- • Kapcsolási rajzot keresek
- • TV hiba, mi a megoldás?
- • Triak és tirisztor helyettesítése
- • Rádióamatőrök topikja
- • Hangszórójavítás (otthon)
- • LED-es világítás
- • Whirlpool mosógép
- • Vásárlás, hol kapható?
- • Autóelektronika
- • Hangváltók (készítése)
- • Vicces - mókás történetek
- • Forrasztópákák - melyik miért jó
» Több friss téma
|
A klónok CH340 Soros-USB illesztőjének drivere ( Letöltés)
Akkor a bekeretezett rész elég lesz?
Kössz az ötletet.
Szia!
Alkalmazásfüggő a dolog. Nem minden esetben kell a kvarc, de a biztosítékbitekre figyelni kell!
Szeretnék segítséget kérni, a C programozás alapjai mennek de a strukúrálás vagy minek nevezzem az még nem.
Építettem egy LiPo akku tesztert mely méri a cellák belső ellenállását, az A/D átalakítója MCP3208, mivel nem túl szabványos SPI protokolja van így az arduino.cc oldalról letöltöttem egy demót hogyan kell használni. A készülék sikerült mér is de azt szeretném hogy az a rész ami az MCP3208-at kezeli egy külön .cpp és .h file-ba legyen, na ennek nem értem a mikéntjét, olyanz már írtam amiben volt egy config.h hogy ne kelljen beállításkor bogarászni a sorok között.
Szóval ez a program:
#include <LiquidCrystal.h>
#include <EEPROM.h>
//#include "MCP3208.h"
#define SELPIN 10
#define DATAOUT 11
#define DATAIN 12
#define SPICLOCK 13
#define LOAD1 2
#define LOAD2 3
#define BTN A5
//kalibracios ertekek:
const float vref = 2.750;
const float cal1 = 1.0038;
const float cal2 = 1.00072;
const float cal3 = 1.0078;
const float cal4 = 0.9902;
const float cal5 = 1.01297;
const float cal6 = 0.9951;
//Cella feszultseg:
float c1;
float c2;
float c3;
float c4;
float c5;
float c6;
//Terhelt cella feszultseg:
float c1l;
float c2l;
float c3l;
float c4l;
float c5l;
float c6l;
//Nyers nem terhelt cella ertekek:
float readvalue1;
float readvalue2;
float readvalue3;
float readvalue4;
float readvalue5;
float readvalue6;
//Nyers terhelt cella ertekek:
float readvalue1l;
float readvalue2l;
float readvalue3l;
float readvalue4l;
float readvalue5l;
float readvalue6l;
// Terhelo ellenallas: 1 Ohm
float r;
// Szamitott cella belso ellenallasok:
float r1;
float r2;
float r3;
float r4;
float r5;
float r6;
// Ossz ellenallas:
float rsum;
//Szamitott terhelo aram:
float current;
//Akku fesz:
float vsum=0;
//Gombhoz kell:
boolean bt;
//Valtozott a cella szam:
boolean change = false;
// A gomb ertekenek beolvasasa:
int val;
// Cellak szama:
byte n = 3;
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
void setup() {
// LCD RS pin to digital pin 4
// LCD Enable pin to digital pin 5
// LCD D4 pin to digital pin 6
// LCD D5 pin to digital pin 7
// LCD D6 pin to digital pin 8
// LCD D7 pin to digital pin 9
//MCP3208 SPI port:
pinMode(SELPIN, OUTPUT);
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK, OUTPUT);
//Terhelo ellenallas FET bekapcsolasa:
pinMode(LOAD1, OUTPUT);
pinMode(LOAD2, OUTPUT);
//
pinMode(BTN, INPUT);
digitalWrite(SELPIN, HIGH);
digitalWrite(DATAOUT, LOW);
digitalWrite(SPICLOCK, LOW);
digitalWrite(LOAD1, LOW);
digitalWrite(LOAD2, LOW);
Serial.begin(115200);
Serial.println("LiPo Tester");
Serial.println();
lcd.begin(20, 4);
n = EEPROM.read(0);
if (n>6) {
n=6;
EEPROM.write(0, n);
}
lcd.setCursor(0, 1);
lcd.print(" Battery Tester ");
lcd.setCursor(0, 2);
lcd.print("Cell number ? ");
lcd.print(n, DEC);
for(int j=0; j<3000; j++) {
delay(1);
val = digitalRead(BTN);
if (val==0) {
change = true;
j=0;
n++;
if(n>6) n=3;
lcd.setCursor(0, 2);
lcd.print("Cell number ? ");
lcd.print(n, DEC);
delay(250);
}
}
if (change== true) EEPROM.write(0, n);
lcd.setCursor(0, 2);
lcd.print(" ");
}
//****************************************************Ezt kellene atvinni a cpp-be.
int read_adc(int channel) {
int adcvalue = 0;
byte commandbits = B11000000;
commandbits|=((channel-1)<<3);
digitalWrite(SELPIN, LOW);
for (int i=7; i>=3; i--) {
digitalWrite(DATAOUT, commandbits & 1<<i);
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
}
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
for (int i=11; i>=0; i--) {
adcvalue += digitalRead(DATAIN)<<i;
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
}
digitalWrite(SELPIN, HIGH);
return adcvalue;
}
//****************************************************
void loop() {
val = digitalRead(BTN);
if(val==1) bt=true;
delay(10);
if(val==0 && bt==true) delay(10);
if(val==0 && bt==true) {
bt=false;
Serial.println("Start Test");
Serial.println("No Load");
digitalWrite(LOAD1, LOW);
digitalWrite(LOAD2, LOW);
delay(100);
readvalue1 = read_adc(7);
Serial.println(readvalue1, DEC);
readvalue2 = read_adc(6);
Serial.println(readvalue2, DEC);
readvalue3 = read_adc(5);
Serial.println(readvalue3, DEC);
if (n >= 4) {
readvalue4 = read_adc(4);
Serial.println(readvalue4, DEC);
}
if (n >=5) {
readvalue5 = read_adc(3);
Serial.println(readvalue5, DEC);
}
if (n>=6) {
readvalue6 = read_adc(2);
Serial.println(readvalue6, DEC);
}
Serial.println();
Serial.println("Load ON");
digitalWrite(LOAD1, HIGH);
//if (readvalue4 < 100) {
digitalWrite(LOAD2, HIGH);
r = 1;
//}
//else {
// r = 2;
//}
delay(100);
readvalue1l = read_adc(7);
Serial.println(readvalue1l, DEC);
readvalue2l = read_adc(6);
Serial.println(readvalue2l, DEC);
readvalue3l = read_adc(5);
Serial.println(readvalue3l, DEC);
if (n>=4) {
readvalue4l = read_adc(4);
Serial.println(readvalue4l, DEC);
}
if (n>=5) {
readvalue5l = read_adc(3);
Serial.println(readvalue5l, DEC);
}
if (n>=6) {
readvalue6l = read_adc(2);
Serial.println(readvalue6l, DEC);
}
Serial.println();
digitalWrite(LOAD1, LOW);
digitalWrite(LOAD2, LOW);
Serial.println("Load OFF");
Serial.println("Stop Test");
Serial.println();
Serial.println();
c4 = 0;
c5 = 0;
c6 = 0;
c1 = (((( readvalue1)/4096)*vref)*((5600+620)/620))*cal1;
c2 = (((( readvalue2-readvalue1)/4096)*vref)*((5600+620)/620))*cal2;
c3 = (((( readvalue3-readvalue2)/4096)*vref)*((5600+620)/620))*cal3;
if (n>=4) c4 = (((( readvalue4-readvalue3)/4096)*vref)*((5600+620)/620))*cal4;
if (n>=5) c5 = (((( readvalue5-readvalue4)/4096)*vref)*((5600+620)/620))*cal5;
if (n>=6) c6 = (((( readvalue6-readvalue5)/4096)*vref)*((5600+620)/620))*cal6;
vsum = c1+c2+c3+c4+c5+c6;
c4l = 0;
c5l = 0;
c6l = 0;
c1l = (((( readvalue1l)/4096)*vref)*((5600+620)/620))*cal1;
c2l = (((( readvalue2l-readvalue1l)/4096)*vref)*((5600+620)/620))*cal2;
c3l = (((( readvalue3l-readvalue2l)/4096)*vref)*((5600+620)/620))*cal3;
if (n>=4) c4l = (((( readvalue4l-readvalue3l)/4096)*vref)*((5600+620)/620))*cal4;
if (n>=5) c5l = (((( readvalue5l-readvalue4l)/4096)*vref)*((5600+620)/620))*cal5;
if (n>=6) c6l = (((( readvalue6l-readvalue5l)/4096)*vref)*((5600+620)/620))*cal6;
current = (c1l+c2l+c3l+c4l+c5l+c6l)/r;
r4 = 0;
r5 = 0;
r6 = 0;
r1 = ((c1-c1l)/current)*1000;
r2 = ((c2-c2l)/current)*1000;
r3 = ((c3-c3l)/current)*1000;
if (n>=4) r4 = ((c4-c4l)/current)*1000;
if (n>=5) r5 = ((c5-c5l)/current)*1000;
if (n>=6) r6 = ((c6-c6l)/current)*1000;
rsum = r1+r2+r3+r4+r5+r6;
Serial.println(c1, 3);
Serial.println(c2, 3);
Serial.println(c3, 3);
Serial.println(c4, 3);
Serial.println(c5, 3);
Serial.println(c6, 3);
Serial.println();
Serial.println(c1l, 3);
Serial.println(c2l, 3);
Serial.println(c3l, 3);
Serial.println(c4l, 3);
Serial.println(c5l, 3);
Serial.println(c6l, 3);
Serial.println(r);
Serial.print(r1);
Serial.println(" mOhm");
Serial.print(r2);
Serial.println(" mOhm");
Serial.print(r3);
Serial.println(" mOhm");
Serial.print(r4);
Serial.println(" mOhm");
Serial.print(r5);
Serial.println(" mOhm");
Serial.print(r6);
Serial.println(" mOhm");
Serial.print(rsum);
Serial.println(" mOhm SUM");
Serial.println();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(r1);
lcd.print(" m ");
lcd.print(r2);
lcd.print(" m ");
lcd.setCursor(0, 1);
lcd.print(r3);
lcd.print(" m ");
if (n>=4) lcd.print(r4);
if (n>=4) lcd.print(" m ");
lcd.setCursor(0, 2);
if (n>=5) lcd.print(r5);
if (n>=5) lcd.print(" m ");
if (n>=6)lcd.print(r6);
if (n>=6)lcd.print(" m ");
lcd.setCursor(0, 3);
lcd.print("SUM");
lcd.print(rsum);
lcd.print ("mOhm ");
lcd.print(vsum);
lcd.print("V");
}
}
Leírtam benne mit kellene átrakni.
Ez lenne az MCP3208.cpp egyenlőre még minden ki van kommentelve:
//#include "MCP3208.h"
/*
int read_adc(int channel) {
int adcvalue = 0;
byte commandbits = B11000000;
commandbits|=((channel-1)<<3);
digitalWrite(SELPIN, LOW);
for (int i=7; i>=3; i--) {
digitalWrite(DATAOUT, commandbits & 1<<i);
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
}
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
for (int i=11; i>=0; i--) {
adcvalue += digitalRead(DATAIN)<<i;
digitalWrite(SPICLOCK, HIGH);
digitalWrite(SPICLOCK, LOW);
}
digitalWrite(SELPIN, HIGH);
return adcvalue;
}
*/
Ez pedig az MCP3208.h:
#ifndef _MCP3208_H_
#define _MCP3208_H_
#endif
A fejlécfájlba (.h) mennek a deklarációk, a forrásfájlba (.cpp) a definíciók. Ez utóbbi már kész van, csak a kommentet kell kiszedni. A fejlécfájl tartalma pedig:
#ifndef _MCP3208_H_
#define _MCP3208_H_
int read_adc(int channel);
#endif
Ezután a főprogramból kiszedheted az átvitt részt (és persze az elején include-olni kell az MCP3208.h-t).
Pár szabály, amivel úgy látom, tisztában vagy, de a teljesség kedvéért leírom: Csak fejlécfájlt include-olunk, forrásfájlt soha. Gyári könyvtárakkal ellentétben a saját fájlokat idézőjelek, nem kacsacsőrök között include-olunk. Minden fejlécfájlba kellenek az #ifndef ... #define ... direktívák, mert különben fennáll a veszélye, hogy több helyre is bemásolódik, és merőrül a linker. Ha olyan globális változót szeretnél használni, amely nem csak az MCP3208.cpp-ben látszik, hanem mindenhol, ahová az MCP3208.h fájlt include-olták, akkor a fejlécfájlban az extern kulcsszóval tudod bejelenteni ( bővebben).
Ha már strukturáljuk a kódot, akkor én átvinném a szoftveres SPI beállításával kapcsolatos dolgokat is (4-7., 88-92. és 98-100. sorok). Például lehetne egy init_adc() nevű függvény, és azt hívnám meg a setupban.
Még nem minden világos, így írtam át a .h fájlt:
#ifndef _MCP3208_H_
#define _MCP3208_H_
int read_adc(int channel);
byte commandbits = B11000000;
#define SELPIN 10
#define DATAOUT 11
#define DATAIN 12
#define SPICLOCK 13
#endif
A következő a hiba:
In file included from LiPo.cpp:3:
MCP3208.h:3: error: 'byte' does not name a type
Ennek az az oka, hogy a byte nem standard C típus. Ha ilyen "arduinós" dolgokat akarsz ott használni, akkor a .h fájl elejére:
Viszont nem fogadtad meg, amit a globális változókról írtam. Ha a commandbits változót csak az MCP3208.cpp fájlban szeretnéd használni, akkor ott definiáld, a fejlécben ne! Ha szeretnéd, hogy kívülről is látsszon, akkor a fejlécben:
A forrásfájlban pedig:
byte commandbits = B11000000;
A hozzászólás módosítva: Feb 10, 2016
A byte -ot megoldottam unsigned char -ral, a B11000000 -ot 0b1100000 -tal, így ez jó már.
Az MCP3208.cpp -be kellett beleírni az arduino.h-t mert még a digitalWrite sem értette.
Még mindig sok sötét folt van, csak sorolom:
public: , class , :: jel stb. A hozzászólás módosítva: Feb 10, 2016
Ezek C++ alapfogalmak, úgyhogy szerintem C++ online tutorialokat olvasgass. Illetve ez egy kiváló könyv, tudom ajánlani. Röviden:
Az osztály (class) az objektumorientált programozás alapköve. Olyan, mint az ANSI C-ben megszokott struktúra, csak a tagjai lehetnek függvények is. Például amikor azt mondod, hogy
SoftwareSerial mySerial(10,11);
akkor valójában a SoftwareSerial osztályt példányosítod mySerial néven. Ezután meg tudod hívni a tagfüggvényeit (például mySerial.available()). A public és a private kulcsszavak egy osztály tagjainak a láthatóságát módosítják. A public függvényekhez és változókhoz hozzá lehet férni kívülről (pl. a SoftwareSerial osztály available() függvénye ilyen), a private tagokat viszont csak az osztály saját tagfüggvényei tudják elérni. A :: (scope resolution operator) kicsit bonyolultabb, most csak egy példát mondok rá. Alapesetben egy osztály tagfüggvényei és tagváltozói csak példányonként léteznek, viszont bizonyos (ún. statikus) tagok önmagukban is értelmesek. Ezekre példányosítás nélkül is lehet hivatkozni, így: ValamiOsztaly::StatikusFuggveny().
Szerintem ezek már olyan dolgok amit iskolában lehet csak rendesen megtanulni. Sajnos én ipari elektronikai technikusként tanultam de a mai világban nem sokat ér az hogy tudom mi B osztályú erősítő, az általánosban basic es Videoton gépek voltak ezért is szeretek ma is abban programozni (BASCOM), középiskolában pascal volt egy évig.
Ahová jártam ott voltak programozó évfolyamtársak, bele is olvasgattam a C könyvükbe, persze amikor odaértem hogy I= I+1 helyett I++ van le is tettem a könyvet hogy na ekkora baromságot, pedig nem kellett volna, azt is furcsállom hogy a C ben van sok olyan matematikai formula amit sehol nem tanultunk általános matematika szintjén.
Mi az ördögnek ehhez iskola? Idő, elszántság, érdeklődés és egy-két jó könyv kell hozzá - meg rengeteg mintapélda.
C könyv
C++ könyv
Sziasztok.
Valaki tudna segíteni? Azt jelzi hogy feltölti de valószínű hogy nem mert ha kilépek programból meg vissza akkor ugyan úgy üres. Mitől lehet ?
Mert már több órája próbálkozok de ugyan úgy semmi
Nem teljesen értem a kérdést... pontosan mi üres?
Már semmi gond működik rendesen.
Annyi kérdésem lenne hogy amit feltöltök rá azt hogy tudom megnézni ha kihúzom meg vissza dugom hogy mi van az arduino-n rajta ?
Azt nem tudod megnézni, feltöltéskor visszaellenőrzi és kiírja hogy sikerült. Utána az benne van ameddig mással felül nem írod.
Értem Köszönöm a segítséget. Csak pár hónapja kezdtem bele és nem tiszta minden.
Magyar oldalakon meg nem nagyon találok róla semmit hogy minek hogy kel pontosan lenni.
PIC-nél is ugyan ez a helyzet ami rá van írva azt nem tudom megnézni csak max újra ráírni valamit ?
Az attól függ. Ha le van zárva (írásvédelem) akkor nem olvasod vissza sehogy.
Visszaolvasni olyannak ahogyan beleírtad sose fogod (tehát kommentek, változónevek, stb), mert a programot a fordító átfordítja gépi-kódra, tehát amit most (vagyis akkor látsz amikor feltöltötted) nem fogsz többet. A visszatöltött kódot viszont (ha nincs levédve) letöltheted és egy másik ugyanolyan PIC-be kiírhatod, másolhatod magyarán. De egy eladásra szánt elektronikába levédik, mert senkinek nem hiányzik hogy másolják a termékét.
Ezt úgy képzeld el, mint most ha belenéznél egy .exe programfájlba, akkor abban is csak "zagyvaságot" látsz, és gondolhatod hogy a program írója nem ezt látta. De ez a zagyvaság a számítógép számára pont érthetô. A hozzászólás módosítva: Feb 11, 2016
Erről az jutott eszembe, nem létezik az arduino gépi kódra disassembler?
Szinte minden processzorra létezhet disassembler (az Arduino pedig nem processzor, csak egy fejlesztôi platform). De a disassemblerel nem az eredeti állapotot állítod vissza, hanem egy olyant, ami (legjobb esetben) újra átfordítható kódot ad (de mivel a változók nevei és a kommentek elvesztek, illetve a program struktúrája is (a fordító programok optimalizálják a kódot) nehéz lesz megérteni hol/mit/miért csinál a kód.
Persze, hogy elvesznek a megjegyzések, ami nincs benne, azt nem is lehet disassemblálni...
De hogy a változó neveket is átszerkeszti azt nem tudtam...
Változó nevek csak neked kellenek, valóságban azok csak a proci memóriájának egy-egy kis szegmensei, azok a gépi-kódban csak a memóriacímet tartalmazzák. Ugyanígy a függvények helyett is csak a programtár egy pontjára utaló szám lesz (ugrási cím). Vagy az sem, csak relatív cím (pl. táblázat). A hozzászólás módosítva: Feb 11, 2016
Sziasztok! Az lenne a kérdésem, hogy egy ilyen programozó jó nanóhoz, unohoz, és megához is? Illetve esetleg due-vel működhet? Előre is köszi!
Minek programozó az arduinok alapból tartalmazzák a programozót annyi az egész, hogy feltelepíted az arduino programot usb-vel csatlakoztatod az arduinot és már programozhatsz is
Az Arduino bootloadert tartalmaz, ezért nem kell külső programozó. Ez soros porton keresztül betölti a programot. Az általad felsorolt lapokon van USB-soros konverter, ezért csak egy USB kábelre van szükséged.
Használhatsz egy Arduinot is programozónak. Feltöltöd rá az Arduino as ISP programmer sketch-et, utána már mint normál programozó működik. Neten utána tudsz nézni ennek, hogy is működik.
Köszi, utána nézek, azért kell, mert van 2 ardum, aminek rossz a soros konvertere, de maga a lap jó, és nem akarom kidobni.
Sziasztok!
Van ez a kód, amihez meg is csináltam a hardvert, működik szépen.
Viszont az a kérdésem, hogy hogyan tudnék más adatokat is kinyerni az autóból?
Ez a program most alap dolgokat ír a kijelzőre, de én kíváncsi lennék például a gázpedál állására és a szívócső nyomására is.
Ebben kérném valaki segítségét.
Köszi.
/*
Arduino Nano OBD reader (OBD protocol KW1281, Audi A4 B5 etc.)
wiring:
D2 --- OBD level shifter input (RX) (e.g. LM339)
D3 --- OBD level shifter output (TX) (e.g. LM339)
A5 --- Arduino 20x4 LCD display SCL
A4 --- Arduino 20x4 LCD display SDA
NOTE: For the level shifting, I used a 'AutoDia K409 Profi USB adapter', disassembled it,
and connected the Arduino to the level shifter chip (LM339) - the original FTDI chip TX line
was removed (so it does not influence the communication)
*/
#include <Wire.h>
#include "LiquidCrystal_I2C.h"
#include "NewSoftwareSerial.h"
//#include <SoftwareSerial.h>
//SoftwareSerial BTSerial(10, 11); // RX | TX
#define pinKLineRX 2
#define pinKLineTX 3
#define pinLED 13
#define pinBuzzer 9
#define pinButton 10
#define ADR_Engine 0x01
#define ADR_Gears 0x02
#define ADR_ABS_Brakes 0x03
#define ADR_Airbag 0x15
#define ADR_Dashboard 0x17
#define ADR_Immobilizer 0x25
#define ADR_Central_locking 0x35
//#define DEBUG 1
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x20 for a 16 chars and 2 line display
NewSoftwareSerial obd(pinKLineRX, pinKLineTX, false); // RX, TX, inverse logic
uint8_t currAddr = 0;
uint8_t blockCounter = 0;
uint8_t errorTimeout = 0;
uint8_t errorData = 0;
bool connected = false;
int sensorCounter = 0;
int pageUpdateCounter = 0;
int alarmCounter = 0;
uint8_t currPage = 1;
int8_t coolantTemp = 0;
int8_t oilTemp = 0;
int8_t intakeAirTemp = 0;
int8_t oilPressure = 0;
float engineLoad = 0;
int engineSpeed = 0;
float throttleValve = 0;
float supplyVoltage = 0;
uint8_t vehicleSpeed = 0;
uint8_t fuelConsumption = 0;
uint8_t fuelLevel = 0;
unsigned long odometer = 0;
String floatToString(float v){
String res;
char buf[16];
dtostrf(v,4, 2, buf);
res=String(buf);
return res;
}
void disconnect(){
connected = false;
currAddr = 0;
}
void lcdPrint(int x, int y, String s, int width = 0){
lcd.setCursor(x,y);
while (s.length() < width) s += " ";
lcd.print(s);
}
void obdWrite(uint8_t data){
#ifdef DEBUG
Serial.print("uC:");
Serial.println(data, HEX);
#endif
obd.write(data);
}
uint8_t obdRead(){
unsigned long timeout = millis() + 1000;
while (!obd.available()){
if (millis() >= timeout) {
Serial.println(F("ERROR: obdRead timeout"));
disconnect();
errorTimeout++;
return 0;
}
}
uint8_t data = obd.read();
#ifdef DEBUG
Serial.print("ECU:");
Serial.println(data, HEX);
#endif
return data;
}
// 5Bd, 7O1
void send5baud(uint8_t data){
// // 1 start bit, 7 data bits, 1 parity, 1 stop bit
#define bitcount 10
byte bits[bitcount];
byte even=1;
byte bit;
for (int i=0; i < bitcount; i++){
bit=0;
if (i == 0) bit = 0;
else if (i == 8) bit = even; // computes parity bit
else if (i == 9) bit = 1;
else {
bit = (byte) ((data & (1 << (i-1))) != 0);
even = even ^ bit;
}
Serial.print(F("bit"));
Serial.print(i);
Serial.print(F("="));
Serial.print(bit);
if (i == 0) Serial.print(F(" startbit"));
else if (i == 8) Serial.print(F(" parity"));
else if (i == 9) Serial.print(F(" stopbit"));
Serial.println();
bits[i]=bit;
}
// now send bit stream
for (int i=0; i < bitcount+1; i++){
if (i != 0){
// wait 200 ms (=5 baud), adjusted by latency correction
delay(200);
if (i == bitcount) break;
}
if (bits[i] == 1){
// high
digitalWrite(pinKLineTX, HIGH);
} else {
// low
digitalWrite(pinKLineTX, LOW);
}
}
obd.flush();
}
bool KWP5BaudInit(uint8_t addr){
Serial.println(F("---KWP 5 baud init"));
//delay(3000);
send5baud(addr);
return true;
}
bool KWPSendBlock(char *s, int size){
Serial.print(F("---KWPSend sz="));
Serial.print(size);
Serial.print(F(" blockCounter="));
Serial.println(blockCounter);
// show data
Serial.print(F("OUT:"));
for (int i=0; i < size; i++){
uint8_t data = s[i];
Serial.print(data, HEX);
Serial.print(" ");
}
Serial.println();
for (int i=0; i < size; i++){
uint8_t data = s[i];
obdWrite(data);
/*uint8_t echo = obdRead();
if (data != echo){
Serial.println(F("ERROR: invalid echo"));
disconnect();
errorData++;
return false;
}*/
if (i < size-1){
uint8_t complement = obdRead();
if (complement != (data ^ 0xFF)){
Serial.println(F("ERROR: invalid complement"));
disconnect();
errorData++;
return false;
}
}
}
blockCounter++;
return true;
}
// count: if zero given, first received byte contains block length
// 4800, 9600 oder 10400 Baud, 8N1
bool KWPReceiveBlock(char s[], int maxsize, int &size){
bool ackeachbyte = false;
uint8_t data = 0;
int recvcount = 0;
if (size == 0) ackeachbyte = true;
Serial.print(F("---KWPReceive sz="));
Serial.print(size);
Serial.print(F(" blockCounter="));
Serial.println(blockCounter);
if (size > maxsize) {
Serial.println("ERROR: invalid maxsize");
return false;
}
unsigned long timeout = millis() + 1000;
while ((recvcount == 0) || (recvcount != size)) {
while (obd.available()){
data = obdRead();
s[recvcount] = data;
recvcount++;
if ((size == 0) && (recvcount == 1)) {
size = data + 1;
if (size > maxsize) {
Serial.println("ERROR: invalid maxsize");
return false;
}
}
if ((ackeachbyte) && (recvcount == 2)) {
if (data != blockCounter){
Serial.println(F("ERROR: invalid blockCounter"));
disconnect();
errorData++;
return false;
}
}
if ( ((!ackeachbyte) && (recvcount == size)) || ((ackeachbyte) && (recvcount < size)) ){
obdWrite(data ^ 0xFF); // send complement ack
/*uint8_t echo = obdRead();
if (echo != (data ^ 0xFF)){
Serial.print(F("ERROR: invalid echo "));
Serial.println(echo, HEX);
disconnect();
errorData++;
return false;
}*/
}
timeout = millis() + 1000;
}
if (millis() >= timeout){
Serial.println(F("ERROR: timeout"));
disconnect();
errorTimeout++;
return false;
}
}
// show data
Serial.print(F("IN: sz="));
Serial.print(size);
Serial.print(F(" data="));
for (int i=0; i < size; i++){
uint8_t data = s[i];
Serial.print(data, HEX);
Serial.print(F(" "));
}
Serial.println();
blockCounter++;
return true;
}
bool KWPSendAckBlock(){
Serial.print(F("---KWPSendAckBlock blockCounter="));
Serial.println(blockCounter);
char buf[32];
sprintf(buf, "\x03%c\x09\x03", blockCounter);
return (KWPSendBlock(buf, 4));
}
bool connect(uint8_t addr, int baudrate){
Serial.print(F("------connect addr="));
Serial.print(addr);
Serial.print(F(" baud="));
Serial.println(baudrate);
tone(pinBuzzer, 1200);
delay(100);
noTone(pinBuzzer);
//lcd.clear();
lcdPrint(0,0, F("KW1281 wakeup"), 20);
lcdPrint(0,1, "", 20);
lcdPrint(0,2, "", 20);
blockCounter = 0;
currAddr = 0;
obd.begin(baudrate);
KWP5BaudInit(addr);
// answer: 0x55, 0x01, 0x8A
char s[3];
lcdPrint(0,0, F("KW1281 recv"), 20);
int size = 3;
if (!KWPReceiveBlock(s, 3, size)) return false;
if ( (((uint8_t)s[0]) != 0x55)
|| (((uint8_t)s[1]) != 0x01)
|| (((uint8_t)s[2]) != 0x8A) ){
Serial.println(F("ERROR: invalid magic"));
disconnect();
errorData++;
return false;
}
currAddr = addr;
connected = true;
if (!readConnectBlocks()) return false;
return true;
}
bool readConnectBlocks(){
// read connect blocks
Serial.println(F("------readconnectblocks"));
lcdPrint(0,0, F("KW1281 label"), 20);
String info;
while (true){
int size = 0;
char s[64];
if (!(KWPReceiveBlock(s, 64, size))) return false;
if (size == 0) return false;
if (s[2] == '\x09') break;
if (s[2] != '\xF6') {
Serial.println(F("ERROR: unexpected answer"));
disconnect();
errorData++;
return false;
}
String text = String(s);
info += text.substring(3, size-2);
if (!KWPSendAckBlock()) return false;
}
Serial.print("label=");
Serial.println(info);
//lcd.setCursor(0, 1);
//lcd.print(info);
return true;
}
bool readSensors(int group){
Serial.print(F("------readSensors "));
Serial.println(group);
lcdPrint(0,0, F("KW1281 sensor"), 20);
char s[64];
sprintf(s, "\x04%c\x29%c\x03", blockCounter, group);
if (!KWPSendBlock(s, 5)) return false;
int size = 0;
KWPReceiveBlock(s, 64, size);
if (s[2] != '\xe7') {
Serial.println(F("ERROR: invalid answer"));
disconnect();
errorData++;
return false;
}
int count = (size-4) / 3;
Serial.print(F("count="));
Serial.println(count);
for (int idx=0; idx < count; idx++){
byte k=s[3 + idx*3];
byte a=s[3 + idx*3+1];
byte b=s[3 + idx*3+2];
String n;
float v = 0;
Serial.print(F("type="));
Serial.print(k);
Serial.print(F(" a="));
Serial.print(a);
Serial.print(F(" b="));
Serial.print(b);
Serial.print(F(" text="));
String t = "";
String units = "";
char buf[32];
switch (k){
case 1: v=0.2*a*b; units=F("rpm"); break;
case 2: v=a*0.002*b; units=F("%%"); break;
case 3: v=0.002*a*b; units=F("Deg"); break;
case 4: v=abs(b-127)*0.01*a; units=F("ATDC"); break;
case 5: v=a*(b-100)*0.1; units=F("°C");break;
case 6: v=0.001*a*b; units=F("V");break;
case 7: v=0.01*a*b; units=F("km/h");break;
case 8: v=0.1*a*b; units=F(" ");break;
case 9: v=(b-127)*0.02*a; units=F("Deg");break;
case 10: if (b == 0) t=F("COLD"); else t=F("WARM");break;
case 11: v=0.0001*a*(b-128)+1; units = F(" ");break;
case 12: v=0.001*a*b; units =F("Ohm");break;
case 13: v=(b-127)*0.001*a; units =F("mm");break;
case 14: v=0.005*a*b; units=F("bar");break;
case 15: v=0.01*a*b; units=F("ms");break;
case 18: v=0.04*a*b; units=F("mbar");break;
case 19: v=a*b*0.01; units=F("l");break;
case 20: v=a*(b-128)/128; units=F("%%");break;
case 21: v=0.001*a*b; units=F("V");break;
case 22: v=0.001*a*b; units=F("ms");break;
case 23: v=b/256*a; units=F("%%");break;
case 24: v=0.001*a*b; units=F("A");break;
case 25: v=(b*1.421)+(a/182); units=F("g/s");break;
case 26: v=float(b-a); units=F("C");break;
case 27: v=abs(b-128)*0.01*a; units=F("°");break;
case 28: v=float(b-a); units=F(" ");break;
case 30: v=b/12*a; units=F("Deg k/w");break;
case 31: v=b/2560*a; units=F("°C");break;
case 33: v=100*b/a; units=F("%%");break;
case 34: v=(b-128)*0.01*a; units=F("kW");break;
case 35: v=0.01*a*b; units=F("l/h");break;
case 36: v=((unsigned long)a)*2560+((unsigned long)b)*10; units=F("km");break;
case 37: v=b; break; // oil pressure ?!
// ADP: FIXME!
/*case 37: switch(b){
case 0: sprintf(buf, F("ADP OK (%d,%d)"), a,b); t=String(buf); break;
case 1: sprintf(buf, F("ADP RUN (%d,%d)"), a,b); t=String(buf); break;
case 0x10: sprintf(buf, F("ADP ERR (%d,%d)"), a,b); t=String(buf); break;
default: sprintf(buf, F("ADP (%d,%d)"), a,b); t=String(buf); break;
}*/
case 38: v=(b-128)*0.001*a; units=F("Deg k/w"); break;
case 39: v=b/256*a; units=F("mg/h"); break;
case 40: v=b*0.1+(25.5*a)-400; units=F("A"); break;
case 41: v=b+a*255; units=F("Ah"); break;
case 42: v=b*0.1+(25.5*a)-400; units=F("Kw"); break;
case 43: v=b*0.1+(25.5*a); units=F("V"); break;
case 44: sprintf(buf, "%2d:%2d", a,b); t=String(buf); break;
case 45: v=0.1*a*b/100; units=F(" "); break;
case 46: v=(a*b-3200)*0.0027; units=F("Deg k/w"); break;
case 47: v=(b-128)*a; units=F("ms"); break;
case 48: v=b+a*255; units=F(" "); break;
case 49: v=(b/4)*a*0.1; units=F("mg/h"); break;
case 50: v=(b-128)/(0.01*a); units=F("mbar"); break;
case 51: v=((b-128)/255)*a; units=F("mg/h"); break;
case 52: v=b*0.02*a-a; units=F("Nm"); break;
case 53: v=(b-128)*1.4222+0.006*a; units=F("g/s"); break;
case 54: v=a*256+b; units=F("count"); break;
case 55: v=a*b/200; units=F("s"); break;
case 56: v=a*256+b; units=F("WSC"); break;
case 57: v=a*256+b+65536; units=F("WSC"); break;
case 59: v=(a*256+b)/32768; units=F("g/s"); break;
case 60: v=(a*256+b)*0.01; units=F("sec"); break;
case 62: v=0.256*a*b; units=F("S"); break;
case 64: v=float(a+b); units=F("Ohm"); break;
case 65: v=0.01*a*(b-127); units=F("mm"); break;
case 66: v=(a*b)/511.12; units=F("V"); break;
case 67: v=(640*a)+b*2.5; units=F("Deg"); break;
case 68: v=(256*a+b)/7.365; units=F("deg/s");break;
case 69: v=(256*a +b)*0.3254; units=F("Bar");break;
case 70: v=(256*a +b)*0.192; units=F("m/s^2");break;
default: sprintf(buf, "%2x, %2x ", a, b); break;
}
switch (currAddr){
case ADR_Engine:
switch(group){
case 3:
switch (idx){
case 0: engineSpeed = v; break;
case 1: supplyVoltage=v; break;
case 2: coolantTemp =v; break;
case 3: intakeAirTemp=v; break;
}
break;
case 11:
switch (idx){
case 1: engineLoad=v; break;
case 2: vehicleSpeed =v; break;
case 3: fuelConsumption=v; break;
}
break;
}
break;
case ADR_Dashboard:
switch (group){
case 1:
switch (idx){
case 0: vehicleSpeed = v; break;
case 1: engineSpeed = v; break;
case 2: oilPressure = v; break;
}
break;
case 2:
switch (idx){
case 0: odometer = v; break;
case 1: fuelLevel = v; break;
}
break;
case 50:
switch (idx){
case 1: engineSpeed = v; break;
case 2: oilTemp = v; break;
case 3: coolantTemp = v; break;
}
break;
}
break;
}
if (units.length() != 0){
dtostrf(v,4, 2, buf);
t=String(buf) + " " + units;
}
Serial.println(t);
//lcd.setCursor(0, idx);
//while (t.length() < 20) t += " ";
//lcd.print(t);
}
sensorCounter++;
return true;
}
void alarm(){
if (alarmCounter > 10) return;
tone(pinBuzzer, 1200);
delay(100);
noTone(pinBuzzer);
alarmCounter++;
}
void updateDisplay(){
if (!connected){
/* if ( (errorTimeout != 0) || (errorData != 0) ){
lcdPrint(0,3, F("err to="));
lcdPrint(7,3, String(errorTimeout), 3);
lcdPrint(10,3, F(" da="));
lcdPrint(14,3, String(errorData), 6);
}
} else {*/
switch (currPage){
case 1:
if (coolantTemp > 99){
lcdPrint(0,1, F("COOL"));
alarm();
} else lcdPrint(0,1, F("cool"));
lcdPrint(6,1,String(coolantTemp),3);
if ( (oilTemp > 99) || ((oilPressure != 30) && (oilPressure != 31)) ){
lcdPrint(10,1,F("OIL "));
alarm();
} else lcdPrint(10,1,F("oil "));
lcdPrint(14,1,String(oilPressure),3);
lcdPrint(0,2, F("rpm "));
lcdPrint(4,2, String(engineSpeed),4);
lcdPrint(10,2, F("km/h "));
lcdPrint(15,2, String(vehicleSpeed, 3));
lcdPrint(0,3, F("fuel "));
lcdPrint(5,3, String(fuelLevel),3);
lcdPrint(10,3, F("odo "));
lcdPrint(14,3, String(odometer),6);
break;
case 2:
if (coolantTemp > 99){
lcdPrint(0,1, F("COOL"));
alarm();
} else lcdPrint(0,1, F("cool"));
lcdPrint(6,1,String(coolantTemp),3);
lcdPrint(10,1, F("air "));
lcdPrint(14,1, String(intakeAirTemp), 3);
lcdPrint(0,2, F("rpm "));
lcdPrint(4,2, String(engineSpeed),4);
lcdPrint(10,2, F("km/h "));
lcdPrint(15,2, String(vehicleSpeed, 3));
lcdPrint(0,3, F("fuel "));
lcdPrint(5,3, String(fuelConsumption),3);
lcdPrint(10,3, F("volt "));
lcdPrint(15,3, String(supplyVoltage),5);
break;
}
}
pageUpdateCounter++;
}
void setup(){
lcd.init();
lcd.backlight();
lcd.init();
pinMode(pinKLineTX, OUTPUT);
digitalWrite(pinKLineTX, HIGH);
pinMode(pinButton, INPUT);
pinMode(pinButton, INPUT_PULLUP);
pinMode(pinBuzzer, OUTPUT);
/*tone(pinBuzzer, 1200);
delay(100);
noTone(pinBuzzer);*/
Serial.begin(19200);
Serial.println(F("SETUP"));
Serial.println(F("START"));
}
void loop(){
if (digitalRead(pinButton) == LOW){
currPage++;
if (currPage > 2) currPage = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(F("page "));
lcd.print(currPage);
errorTimeout = 0;
errorData = 0;
while (digitalRead(pinButton) == LOW);
}
switch (currPage){
case 1:
if (currAddr != ADR_Dashboard){
connect(ADR_Dashboard, 9600);
} else {
readSensors(1);
readSensors(2);
readSensors(50);
}
break;
case 2:
if (currAddr != ADR_Engine) {
connect(ADR_Engine, 9600);
} else {
readSensors(3);
readSensors(11);
}
break;
}
updateDisplay();
}
Akkor neked egy TTL soros-USB adapter kellene, de persze ezt is megrendelheted mert nem összeg egyik sem.
Itten olvastam hogy HD4478 lcd-nel max 8 speci karaktert lehet definialni. Ez igaz ?
Ha tobb ilyen karakterre van szuksegem, akkor azt a loop reszbe, vagyis helybe lehet definialni es amikor ezt a lepest atlepi az Arduino akkor elfelejti oket es hasznalja normalis modon az elore definialtakat (ami a ram-ba van) ?
Vagy pedig ha osszesen tobb mint 8 ilyen karakterem van akkor mindegyiket helybe kell definialni, letrehozni (a flash-ba) ?
|
|