Zobacz pełną wersję : [Ogólne] ARDUINO - gdy w aucie Ci czegoś brakuje...


tedi_k
23-02-2022, 23:27
Wątek nie dotyczy stricte multimediów samochodowych, ale postanowiłem go umieścić w tym dziale jako "odnoszący się do szeroko rozumianej elektroniki"...:p

Rzecz będzie o tym, "co zrobić jeśli w aucie nam czegoś brakuje a mamy pomysł jak to uzupełnić".

Czasy, gdy wystarczył jakiś przekaźnik, trochę przewodów i szczypce płaskie "były wzięły i bezpowrotnie minęły"..:p

Dzisiaj wszystko sterowane jest sterownikami wpiętymi w sieć CAN albo LIN i uruchamiane zazwyczaj w oparciu o komunikaty na tych magistralach.

Tak więc aby (to są przykłady...):
- dodać tylne światło przeciwmgielne w samochodzie Escape 2013-2019 (tym z USA...) i by to działało "jak z fabryki" (europejskiej...) potrzebne jest "magiczne pudełeczko" podpięte do szyny CAN;
- by działała (jak z fabryki...) podgrzewana przednia szyba w autach z USA czasem (o dziwo...) wystarczą przekaźniki (po wymianie panelu przycisków klimatyzacji na wersję EU) a czasami znów trzeba użyć "magicznego pudełeczka" wpiętego w CAN.

Takich przykładów można mnożyć, ale "nie o tym jest ten wątek"...

Postaram się tu pokazać - na rzeczywistym przykładzie - jak rozwiązuje się problemy podobne do powyżej wskazanych.

Opis będzie dotyczył mojego Mitsubishi Outlandera 2019 PHEV - w którym (dość dawno temu...) wymieniłem szybę przednią na podgrzewaną (identyczną jak w Fordzie...) bo mi się trafiła za akceptowalne pieniądze i "czułem wewnętrzną potrzebę jej montażu"...:p
W Mitsubishi grzana szyba przednia (w skrócie tu nazywana HWS) sterowana jest przez panel klimatyzacji. Musi on być w wersji obsługującej tę opcję. Niestety mój panel (P/N 7820B232) nie obsługiwał tej opcji, a takiego co mógłby go skutecznie w tym zastąpić (P/N 7820B231) na całym świecie na Allegro, eBay, Amazon, OLX i gdzie tam jeszcze nie można było przez ponad rok znaleźć. Nowy w ASO przez Mitsubishi został wyceniony na "drobne" 1100 (tysiąc sto...) EURO! - więc "nie rozważałem tej opcji"...
W związku z powyższym, by moja HWS "nie marnowała się w bezczynności" musiałem jakoś sobie "auto uzupełnić".

Na początek postanowiłem spróbować "przerobić" (uzupełnić) mój panel 7820B232 do wersji 7820B231 - porobiłem stosowne zdjęcia płytek panelu 231 i z kolegą zabraliśmy się za uzupełninie brakujących elementów.
Udało nam się wszystko pouzupełniać (jak nam się wydawało...) zgodnie z posiadanymi zdjęciami i - o dziwo - panel dalej żył... Niestety szczęścia mieliśmy "tylko połowę". Okazało się, że funkcjonuje poprawnie cały tor wejściowy (naciśnięcie klawisza podgrzewania szyby jest "zauważane" przez panel klimatyzacji, są kontrolowane wszelkie warunki włączenia szyby oraz czas jej grzanie itp., kontrolka podgrzewania szyby na mojej fabrycznej navi się pokazuje - niestety tor wyjściowy sygnału "nie ruszył" i przekaźniki uruchamiania przetwornicy napięcia do grzania HWS nie włączają się...
Czyli mamy tu sytuację "wypisz wymaluj" dokładnie jak w owym Escape przywołanym powyżej...:one:
Tak więc w moim rozumieniu "szklanka była do połowy PEŁNA" i mogłem zacząć działać by ją "napełnić do pełna"...:p

No i tu wreszcie jest miejsce by na scenę wszedł nasz główny bohater - ARDUINO...

Sytuacja jest niejako "wymarzona" do jego użycia - najwyraźniej generowane są stosowne komunikaty CAN o włączeniu/wyłączeniu HWS - no bo nawigacja "umie" włączyć ikonę uruchomionej podgrzewanej szyby... Wystarczy więc "tylko" znaleźć te komunikaty i użyć ich do wypracowania "brakujących" sygnałów załączenia przekaźnika włączającego przetwornicę napięcia do podgrzewania HWS.

No więc "DO DZIEŁA".

Do realizacji mojego projektu wybrałem "niedawno odkryty" mardzo przyzwoity moduł z MCU ATtiny167 - DigiSpark ATtiny 167 Pro - https://images92.fotosik.pl/575/73511c3d896afdbdgen.jpg (https://images92.fotosik.pl/575/73511c3d896afdbd.jpg)

Sam MCU Atmel ATtiny167 opisany jest w stosownym datasheet (http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8265-8-bit-AVR-Microcontroller-tinyAVR-ATtiny87-ATtiny167_datasheet.pdf) - więc nie będę tu przytaczał opisu, ale dodam, iż bardzo małe rozmiary modułu, 16kB flash (po odjęciu obszaru bootloadera pozostaje ponad 14kB pamięci na program użytkownika), dostęp niezbędnych interfejsów (jako ciekawostkę dodam, iż wbudowany USART posiada możliwość działania jako kontroler LIN...) czynią z tego MCU wprost idealne narzędzie do tworzenia całkiem sporych projektów.
Niestety - jak większość MCU na jądrze AVR - nie ma on wbudowanego interfejsu CAN - więc niezbędne jest użycie zewnętrznego modułu.
Akurat w tym obszarze "nie ma tłoku" i narzuca się użycie najpopularniejszego modułu opartego o chip MCP2515.

https://images89.fotosik.pl/574/62f6174439047cefgen.jpg (https://images89.fotosik.pl/574/62f6174439047cef.jpg)

Dla zapewnienia niezawodności działania urządzenia w aucie ostatnio przestałem polegać na niezawodności stabilizatorów liniowych montowanych na modułach arduino (zbyt dużo poszło mi ich "z dymem"...) i zacząłem stosować miniaturowe przetwornice napięcia - bardzo mi się spodobała taka:

https://images91.fotosik.pl/574/3ec9c59f41e3be20gen.jpg (https://images91.fotosik.pl/574/3ec9c59f41e3be20.jpg)

(tu sfotografowana "z resztą towarzystwa"...) aktualnie dostępna na tej aukcji Allegro (https://allegro.pl/oferta/przetwornica-mini-360-dc-dc-stepdown-1-17v-1-8a-9838986819)

Jak widać na zdjęciu - moduł MCP2515 (mimo, że już przeze mnie sporo "przycięty"...) to w stosunku do przetwornicy i ATtiny167 "prawdziwy gigant"...

Właśnie ze względów na te rozmiary oraz naprawdę spore możliwości - polecam taki zestaw do realizacji zdecydowanej większości projektów "w aucie" i nie tylko...

Ponieważ już wszystko widać "na czym działamy", to pora wreszcie przystąpić do "clou programu" - zaprezentować sam program właśnie... W nomenklaturze Arduino zwany "sketch".

Prezentowany poniżej sketch napisany został "w wersji maksymalnej" - w obsłudze magistrali CAN uzywa filtrów sprzętowych modułu MCP2515 oraz przerwań generowanych przez ten moduł.
Ponadto - trochę dla "zabawy" oraz z tego powodu, ze mój moduł działa w aucie caly czas (także na wyłączonym zapłonie) - to sketch używa trybu obniżonego poboru energii (uśpienia modułu) właśnie w czasie gdy zapłon jest wyłączony. Oczywiście tryb "sleep" - jak wyżej napisałem - zaprogramowałem "przykładowo" i "dla zabawy" bo cały zestaw zużywa poniżej 100mA...

Oto cały kod programu:
// sketch napisany dla modułu ATtiny167 Digispark Pro
// ==================================================
// Moduł CAN MCP2515 obsługiwany z użyciem przerwań
// oraz masek/filtów do selekcji odbieranych ID ramek
// ==================================================
// w czasie gdy zapłon jest wyłączony (stan !_READY)
// MCU ATtiny167 jest w stanie niskiego poboru energii
//
// (c) Tedi_k 2022 - użycie oraz modyfikacje dopuszczone
// pod warunkiem wskazania autora
//
#include <SPI.h>
#include <mcp2515.h>
#include <avr/sleep.h>

#define RDY_LED 1 // wewnętrzna (w module) kontrolka stanu READY/HSW ON (jak miga)
#define HWS_OUT 2 // grzana przednia szyba - przekaźnik/tanzystor wystawić ma masę.
#define PINT0 3 // INT0 jest na pinie PB6 - a to jest D3
#define HWS_IN 5 // włącznik grzania HSV - sterowanie masą
#define CS_MCP2515 9 // chip select modułu CAN (reszta na standardowym SPI)

#define NUSED1 0 // lista pinów nieużywanych - do inicjalizacji dla trybu sleep()
#define NUSED2 4
#define NUSED3 6
#define NUSED4 7
#define NUSED5 12

#define _SW_time 2500UL // force_ON wymaga trzymania przełącznika HWS wciśniętego przez 2,5 sekundy
#define _ON_time 180000UL // w trybie force_ON HWS grzeje przez 180 sekund (3 minuty)
#define _BLNK_time 500UL // blink co 0,5 sekundy
#define _CAN_time 2000UL // 2 sek. bez ramki na CAN == "śmierć CAN"

#define ON true
#define OFF false

#define REL_ON HIGH // sterowanie przekaźnikiem/tranzystorem z portu (wysokim)
#define REL_OFF LOW

#define LED_ON HIGH // dioda-kontrolka sterowana z portu (wysokim)
#define LED_OFF LOW

boolean wrk, WINDSHIELD_H_ON, force_ON, prev_HWS_IN;
boolean _READY, _blnk;
uint32_t _t_ON, _t_BLNK, _t_CAN; // czas (millis()) włączenia trybu force_ON oraz sterowanie miganiem diody
int temp;

volatile bool interrupt = false;

struct can_frame canMsg;
MCP2515 mcp2515(CS_MCP2515); // pin CS dla interfejsu SPI do modułu mcp2515

void irqHandler() {
interrupt = true;
}
void (* resetFunc) (void) = 0; // "Programowe" wykonanie RESET modułu (skok pod adres "0").

void setup() {
WINDSHIELD_H_ON = force_ON = _READY = false;
_blnk = true;
prev_HWS_IN = HIGH;
temp = 0;
pinMode(HWS_OUT, OUTPUT);
pinMode(RDY_LED, OUTPUT);
pinMode(HWS_IN, INPUT_PULLUP);
pinMode(PINT0, INPUT_PULLUP);

pinMode(NUSED1, OUTPUT); // Inicjalizacja pinów nieużywanych dla potrzeb trybu oszczędzania energii
pinMode(NUSED2, OUTPUT);
pinMode(NUSED3, OUTPUT);
pinMode(NUSED4, OUTPUT);
pinMode(NUSED5, OUTPUT);
digitalWrite(NUSED1, LOW);
digitalWrite(NUSED2, LOW);
digitalWrite(NUSED3, LOW);
digitalWrite(NUSED4, LOW);
digitalWrite(NUSED5, LOW);

digitalWrite(RDY_LED, LED_OFF); // Wyłączenie LED (stan "zanegowany")

mcp2515.reset();
mcp2515.setBitrate(CAN_250KBPS, MCP_16MHZ); // Sets CAN at speed 250KBPS and Clock 16MHz - MS-CAN
// (digitalPinToInterrupt(PINT0) - nie kompiluje się)
mcp2515.setFilterMask(MCP2515::MASK0, false, (uint32_t) 0x3ff); // Trzeba zainicjować obie maski w MCP2515 (ramki poniżej diagnostycznych)
mcp2515.setFilterMask(MCP2515::MASK1, false, (uint32_t) 0x3ff);

mcp2515.setFilter(MCP2515::RXF0, false, (uint32_t) 0x315); // MCP2515 ma 6 filtrów (ramka z temperaturą zewnętrzną)
mcp2515.setFilter(MCP2515::RXF1, false, (uint32_t) 0x188); // ramka ze statusem klimatyzacji

mcp2515.setNormalMode(); // setNormalMode() MUSI być za definicjami masek i filtrów

attachInterrupt(INT0, irqHandler, FALLING); // INT0 dla przyjętego pinu 6 do podłączenia INT z MCP2515

set_sleep_mode(SLEEP_MODE_IDLE); // Aby działało SPI nie można użyć wyższego trybu uśpienia

_t_BLNK = millis();
while(CAN_MsgRead() != MCP2515::ERROR_OK) led_BLNK(); // sprawdzamy "czy CAN żyje"...
digitalWrite(RDY_LED, LED_OFF); // Wyłączenie LED (stan "zanegowany")
_t_ON =_t_CAN = millis();
}

void loop() {
if ((uint32_t) (millis() - _t_CAN) > _CAN_time) { // CAN "umarł" - RESET całego sterowania
HWS(OFF);
resetFunc();
}

if (interrupt && CAN_MsgRead() == MCP2515::ERROR_OK) {
interrupt = false;
_t_CAN = millis(); // jest ramka na CAN
switch ((unsigned int)canMsg.can_id) {
case (unsigned int) 0x315: // ramka z temperaturą zewnętrzną
temp = (int) (canMsg.data[6]>>1) - 40;
break;

case (unsigned int) 0x188: // ramka statusu klimatyzacji
if (canMsg.data[0] == (byte) 0x03)
_READY = true;
else // po wyłączeniu silnika natychmiast wyłączamy HWS
_READY = force_ON = false;

{
byte s = canMsg.data[2];
s &= 0xF0;
if (_READY && s == 0x80) {
HWS(ON); // windshield ON
force_ON = false; // HWS włączona wtrybie normalnym - kasuje to tryb force_ON
}
else
if (_READY && s != 0x80 && !force_ON) {
if (WINDSHIELD_H_ON) // HWS właśnie wyłączana w trybie normalnym
prev_HWS_IN = LOW; // zabezpieczenie przed interpretacją przycisku HWS
HWS(OFF); // HWS wyłączona w trybie normalnym
}
}
break;

default: // Przy prawidłowych filtrach tu nigdy nie trafia...
break;
}
}

if (!WINDSHIELD_H_ON)
digitalWrite(RDY_LED, (_READY) ? LED_ON : LED_OFF);
else
led_BLNK(); // Przy włączonej HSW kontrolka led miga

if (!_READY) {
HWS(OFF); // natychmiastowe wyłączenie HWS w trybie "not READY"
sleep_enable();
sei();
sleep_mode(); // przejście w stan uśpienia do czasu przerwania INT0 od następnej ramki CAN
sleep_disable();
}
else {
if (temp <= 5) return; // poniżej 5st. C jedynie tryb "normalny" HWS

if (!force_ON && WINDSHIELD_H_ON) return; // Jeśli HWS włączona w trybie normalnym to nic do zrobienia

wrk = digitalRead(HWS_IN);
if (force_ON) {
if(wrk == LOW && wrk == prev_HWS_IN)
return; // czekamy na puszczenie klawisza HWS;
if (wrk == LOW)
HWS(OFF); // ręczne wyłączenie HWS w trybie force_ON
if ((uint32_t) (millis() - _t_ON) > _ON_time)
HWS(OFF); // upłynął czas włączenia HWS w trybie force_ON
prev_HWS_IN = wrk;
return;
}

if (wrk == HIGH) {
prev_HWS_IN = HIGH;
return; // przycisk włączenia HWS nie jest wciśnięty;
}

if (wrk != prev_HWS_IN) { // obsługa włączania tryby force_ON
if (prev_HWS_IN == HIGH) // właśnie wciśnięto przycisk HWS
_t_ON = millis();
prev_HWS_IN = LOW;
}
else // klawisz HWS nadal wciśnięty...
if ((uint32_t) (millis() - _t_ON) > _SW_time) {
_t_ON = millis();
force_ON = true;
HWS(ON);
}
}
}

void led_BLNK() {
if ((uint32_t) (millis() - _t_BLNK) > _BLNK_time) {
_t_BLNK = millis();
_blnk = !_blnk;
}
digitalWrite(RDY_LED, _blnk);
}

void HWS(bool on_off) {
digitalWrite(HWS_OUT, (on_off) ? REL_ON : REL_OFF); // przekaźnik HWS
WINDSHIELD_H_ON = on_off;
if (!on_off && force_ON) {
force_ON = false;
_t_ON = millis();
}
}

int CAN_MsgRead() {
uint8_t irq = mcp2515.getInterrupts();

if (irq & MCP2515::CANINTF_RX0IF) return(mcp2515.readMessage(MCP2515::RXB0, &canMsg));
if (irq & MCP2515::CANINTF_RX1IF) return(mcp2515.readMessage(MCP2515::RXB1, &canMsg));
return(MCP2515::ERROR_NOMSG);
}


Kod ten można traktować jako "szablon" na wszystkie podobne przypadki.
Po podmianie logiki związanej z tą moją HWS na logikę np. włączania "tylnego światła przeciwmgielnego w Escape" zmieni się w powyższej treści nie więcej niż jakieś 10% kodu...

Kluczowym problemem - który w tym poście nie jest nawet sygnalnie opisany ... - jest zidentyfikowanie ramek CAN do użycia w naszym projekcie...

Ale tego to już nie da się opisać "pokrótce". To po prostu trzeba umieć zrobić. Sporo godzin z komputerem w aucie, cierpliwość, spostrzegawczość i doświadczenie to zestaw niezbędnych cech...
Każdy tu musi już sobie jakoś sam poradzić...
Jak łatwo sprawdzić - "w całym Internecie" nie da się znaleźć informacji w jakiej ramce CAN w Mitsubishi Outlanderze PHEV jest status "włączonego zapłonu"... A jednak "jest namierzony"...:one:

Jak ktoś będzie chciał skonsultować swoje pomysły - to służę pomocą w tym wątku.

dzwiedziu
24-02-2022, 08:24
prawdziwy gigant
Nie lepiej było dać leonardo?
Obyło by się bez przetwornicy i can ;)

tedi_k
24-02-2022, 10:48
Nie lepiej ...

To jak wiadomo zależy od przyjętych kryteriów oceny...:p
Wg moich kryteriów (1. Wielkość pudełka, 2. Cena komponentów, 3. Łatwość programowania, dostępność bibliotek, stabilność kodu, 4. Niezawodność w środowisku automotive/odporność na poziom napięcia zasilania, 5. Przydatność do użycia w innych/podobnych projektach) pokazane powyżej rozwiązanie jest zdecydowanie najlepsze.

Niezależnie od pomysłów "na czym to zrobić" najważniejsza i tak jest ta radość: "działa tak jak chciałem! Jak w Fordzie!!!":wink:

Widok z dzisiejszego poranka...

https://images89.fotosik.pl/575/49f281c4f9b5c215gen.jpg (https://images89.fotosik.pl/575/49f281c4f9b5c215.jpg)

tedi_k
26-02-2022, 16:14
Dzisiaj coś specjalnego dla Kolegi Barixon - tu (https://forum.fordclubpolska.org/showpost.php?p=3396207&postcount=1) zostało zadane pytanie o dołożenie grzanej szyby do Explorera USA.

Tak jak pisałem w pierwszym poście - można spróbować to zrobić "jak z fabryki", ale wtedy konieczna jest co najmniej wymiana panelu przycisków klimatyzacji na wersję EU.
Pisałem też, że nie koniecznie może być to wykonalne (osobiście nie sprawdzałem, czy dla Explorera taki panel klawiszy istnieje...).

Można też to zrobić "w sposób uproszczony - aby tylko dało się włączyć i wyłączyć grzanie szyby oraz by to grzanie działało przez określony czas i samo się wyłączało".

Ten post będzie o takim przypadku.

Zresztą znów sprowokowany jest "ze świata Mitsubishi", bo kolega "od tych aut" poprosił mnie o zrobienie takiego "prościutkiego modułu" do załączania przedniej szyby w modelach benzynowych (a nie PHEV jak mój opisany wcześniej moduł).

Tym razem (ponieważ to "prościutki moduł") postanowiłem go zrobić na ATtiny 85.

https://cdn3.botland.com.pl/55182-pdt_540/digispark-attiny85-mini-mikrokontroller-5v.jpg

Tu jest (https://botland.com.pl/plytki-zgodne-z-arduino-pozostale/14010-digispark-attiny85-mini-mikrokontroller-5v-5904422342371.html) cały opis tej płytki.

Schemat płytki jest prościutki:

https://images90.fotosik.pl/574/d2b47b1c2d912bd0gen.jpg (https://images90.fotosik.pl/574/d2b47b1c2d912bd0.jpg)

Oczywiście dodałem do układu "swoją ulubioną przetwornicę", by zapewnić jakiś racjonalny poziom niezawodności całego rozwiązania.

https://images92.fotosik.pl/576/2c73629a70be304egen.jpg (https://images92.fotosik.pl/576/2c73629a70be304e.jpg)

Do modułu trzeba jeszcze dodać 2 tranzystory i 2 rezystory po jednym dla każdego z 2 wyjść sterujących załączaniem przekaźników każdej z połówek grzanej przedniej szyby.
Układ sterujący może być taki sam (na tranzystorze BC548 ) jak w module ASSoff opisanym swego czasu w dziale Mondeo MK5.

Kod programu:

// sketch napisany dla modułu ATtiny85
// ==================================================
// Moduł sterujący włączaniem grzanej przedniej szyby
// Bez kontroli warunków (temperatury) i bez uzależnienia czasu grzania szyby
// od tych warunków. Sterowany jedynie zasilaniem samego modułu
// oraz przyciskiem włączenia/wyłączenia grzania.
// ==================================================
// Moduł powinien być zasilany jedynie w stanie dopuszczającym włączenie HWS
// - czyli z uruchomionym silnikiem.
// Przekaźniki HWS1 i HWS2 od włączania grzania połówek szyby powinny być zasilane
// po włączeniu zapłonu a sterowane masą z odpowiednio wyjścia HWS_OUT1 i HWS_OUT2 z modułu.
//
// (c) Tedi_k 2022 - użycie oraz modyfikacje dopuszczone
// pod warunkiem wskazania autora
//

#define RDY_LED 1 // wewnętrzna (w module) kontrolka stanu READY/HWS ON (jak miga)
#define HWS_OUT1 2 // grzana przednia szyba - przekaźnik/tanzystor wystawić ma masę.
#define HWS_OUT2 3 // INT0 jest na pinie PB6 - a to jest D3
#define HWS_IN 0 // włącznik grzania HSV - sterowanie masą


#define _SW_time 500UL // force_ON wymaga trzymania przełącznika HWS wciśniętego przez 0,5 sekundy
#define _ON_time 330000UL // grzeje przez 330 sekund (5,5 minuty)
#define _BLNK_time 500UL // blink co 0,5 sekundy
#define _HWS1_2_delay 5000UL // Odstęp 5 sekund pomiędzy włączeniem połówek HWS

#define ON true
#define OFF false

#define REL_ON HIGH // sterowanie przekaźnikiem/tranzystorem z portu (wysokim)
#define REL_OFF LOW

#define LED_ON HIGH // dioda-kontrolka sterowana z portu (wysokim)
#define LED_OFF LOW

boolean wrk, WINDSHIELD_H_ON, prev_HWS_IN;
boolean _blnk, wait_SW;
uint32_t _t_ON, _t_BLNK, _t_CAN; // czas (millis()) włączenia trybu force_ON oraz sterowanie miganiem diody

void setup() {
WINDSHIELD_H_ON = wait_SW = false;
_blnk = true;
prev_HWS_IN = HIGH;
pinMode(HWS_OUT1, OUTPUT);
pinMode(HWS_OUT2, OUTPUT);
pinMode(RDY_LED, OUTPUT);
pinMode(HWS_IN, INPUT_PULLUP);

digitalWrite(RDY_LED, LED_OFF); // Wyłączenie LED
digitalWrite(HWS_OUT1, REL_OFF); // Wyłączenie sygnałów HWS1
digitalWrite(HWS_OUT2, REL_OFF); // i HWS2

while (!digitalRead(HWS_IN)); // Przy włączaniu zapłonu przycisk HWS musi być zwolniony (stan niski)
delay(_SW_time);
while (!digitalRead(HWS_IN)); // test zwolnionego przycisku przez 0,5 sek.

_t_BLNK = _t_ON = millis();
}

void loop() {
HWS(WINDSHIELD_H_ON);

if (!WINDSHIELD_H_ON)
digitalWrite(RDY_LED, LED_ON);
else
led_BLNK(); // Przy włączonej HWS kontrolka led miga

wrk = digitalRead(HWS_IN);
if(wrk == LOW && wrk != prev_HWS_IN) { // Klawisz HWS właśnie został naciśnięty
_t_ON = millis();
prev_HWS_IN = LOW;
return;
}

if(wrk == LOW && wrk == prev_HWS_IN && wait_SW)
return; // Czekamy na puszczenie klawisza HWS;

if(wrk == LOW && wrk == prev_HWS_IN) {
if ((uint32_t) (millis() - _t_ON) > _SW_time)
return; // Oczekiwanie na zadany czas utrzymania klawisza wciśniętym
else { // Klawisz wciśnięty odpowiednio długo
if (!wait_SW) // Jeśli jeszcze nie jest obsłużony
WINDSHIELD_H_ON = !WINDSHIELD_H_ON; // to włączenie lub wyłączenie HWS w zależności od jej aktualnego stanu
wait_SW = true; // Klawisz już obsłużony, oczekwanie na jego puszczenie
return;
}
}

if (wrk == HIGH) { // Klawisz puszczony, zezwolenie na ponowną obsługę wciśnięcia klawisza
prev_HWS_IN = HIGH;
wait_SW = false;
return;
}
}

void led_BLNK() {
if ((uint32_t) (millis() - _t_BLNK) > _BLNK_time) {
_t_BLNK = millis();
_blnk = !_blnk;
}
digitalWrite(RDY_LED, _blnk);
}

void HWS(bool on_off) {
if (on_off) {
if (!WINDSHIELD_H_ON) _t_ON = millis();
digitalWrite(HWS_OUT1, REL_ON); // Przekaźnik HWS1 pierwszej połowy
WINDSHIELD_H_ON = ON;
if ((uint32_t) (millis() - _t_ON) > _HWS1_2_delay)
digitalWrite(HWS_OUT2, REL_ON); // Przekaźnik HWS2 drugiej połowy
if ((uint32_t) (millis() - _t_ON) > _ON_time)
WINDSHIELD_H_ON = OFF;
}
else {
digitalWrite(HWS_OUT1, REL_OFF); // Wyłączenie przekaźnika HWS1 pierwszej połowy
digitalWrite(HWS_OUT2, REL_OFF); // Wyłączenie przekaźnika HWS2 drugiej połowy
WINDSHIELD_H_ON = OFF;
}
}


Całość działa zaraz po podaniu zasilania na moduł.
Trzeba więc zadbać o to, by moduł załączał się jedynie w sytuacji, gdy można włączać podgrzewaną szybę przednią.
Może być to na przykład układ z wykorzystaniem jakiegoś modułu od uruchamiania świateł DRL (zwykle takie moduły mierzą napięcie ładowania jako wskaźnik, że silnik jest już uruchomiony).

Do włączania podgrzewania szyby można wykorzystać dowolny przycisk niestabilny ("naciskany") podający masę na wejście HWS_IN modułu.

Całość jak widać jest "uproszczona do granic możliwości". Są zwolennicy i takich rozwiązań...

tedi_k
28-02-2022, 19:57
W uzupełnieniu tego postu powyżej (o "prostym module...") - zamieszczam zdjęcie modułu w pełni zmontowanego i okablowanego.
Zamontowane są tranzystory sterowania przekaźnikami oraz "na wszelki wypadek" - tzw. "diody gaszące". Te ostatnie niezbędne są do zniwelowania "napięcia pasożytniczego" generującego się na indukcyjności (na cewce elektromagnesu przekaźnika) przy jej wyłączaniu.
Moduł gotowy jest do "zamknięcia w (magicznym?:wink:) pudełku".

https://images91.fotosik.pl/575/95e9c18379f36261gen.jpg (https://images91.fotosik.pl/575/95e9c18379f36261.jpg)

Uprzejmie proszę NIE OCENIAĆ mych "zdolności lutowmniczych" - gdyż "są żadne. Nie lubię się nimi "chwalić" :oops:, ale inaczej nie będzie jakiegokolwiek przykładu "jak może wyglądać taki "prościutki modulik" po zmontowaniu...

tedi_k
03-03-2022, 17:29
Wczoraj - w czasie uruchamiania układu z użyciem docelowych przekaźników włączania podgrzewania połówek HWS - zauważyłem dość uciążliwą właściwość układów ATtiny.
Dotyczy to prawdopodobnie wszystkich układów nowych serii ATtiny, posiadający emulowany/wirtualny port USB. Port taki zrealizowany jest programowo z wykorzystaniem standardowych we/wy cyfrowych.
W przypadku ATtiny85, linia D+ portu USB zrealizowana jest na wyjściu D2 a linia D- na wyjściu D3.
Aktualnie zwykle dla tej rodziny układów rolę bootloadera pełni 'micronucleus' potrafiący dokonywać ładowania zawartości pamięci flash z wykorzystaniem wirtualnego portu USB. Aby móc sprawdzić, czy ma być wykonana funkcja wgrywania zawartości flash, 'micronucleus' musi zainicjalizować ów wirtualny port USB.
No i tu zaczynają się potencjalne problemy.
Jak łatwo sprawdzić wyżej w kodzie programu dla "prościutkiego modułu", ja przeznaczyłem D3 jako linię wyjściową do sterowania jednym z tranzystorów BC548 załączających przekaźnik. Sterowanie tranzystorem polega na podaniu sygnału wysokiego na jego bazę. Natomiast 'micronucleus' najprawdopodobniej linię D3 pełniącą rolę D- dla portu USB inicjalizuje jako INPUT_PULLUP - co skutkuje wystawieniem (mimo, że to linia INPUT) stanu wysokiego na zewnątrz układu. To z kolei powoduje "otwarcie" tranzystora i ZAŁĄCZENIE PRZEKAŹNIKA! Wszystko to dzieje się ZANIM sketch wejdzie w procedurę SETUP i poustawia parametry wejść/wyjść.
Takie zachowanie powodowało "klikanie" przekaźnika przy każdym włączeniu zasilania modułu - a więc w tym przypadku przy każdym włączeniu zapłonu. Sytuacja była nie do zaakceptowania: przekaźnik przecież załącza duży prąd na szybę i takie "ciągłe" włączanie wyłączanie (mimo, że na milisekundę) spowodowało by wypalenie styków przekaźnika w bardzo krótkim czasie.
Musiałem więc cały układ przeprojektować i przebudować, by tego uniknąć. Zamieniłem więc linię D0, która była dotychczas wejściem sygnału z przełącznika z linią D3 miejscami i "wszystko zrobiło się OK".

Tak więc moja porada dla chcących używać mikrokontrolerów z nowych rodzin ATtiny z portem wirtualnym USB - zwracać szczególną uwagę na sposób użycia linii danych, na których zrealizowana jest linia D- portu USB. W ATtiny85 jest to D3, w ATtiny167 jest to D4.
Należy unikać stosowania tych linii jako wyjściowych - w szczególności do sterowania tranzystorami. Przy inicjalizacji bootloadera układu (po włączeniu zasilania) może mieć to niespodziewane i nieprzewidziane konsekwencje.

Barixon
04-03-2022, 13:48
Dzisiaj coś specjalnego dla Kolegi Barixon - tu (https://forum.fordclubpolska.org/showpost.php?p=3396207&postcount=1) zostało zadane pytanie o dołożenie grzanej szyby do Explorera USA.


Super , podane na tacy w zasadzie , zostają tylko chęci i troszkę wiedzy , jak skończę wstawie foto z efektu finalnego , dziękuje

tedi_k
04-03-2022, 20:05
No to na koniec omawiania "prostego moduliku" jeszcze jedna ważna informacja - nie ma sensu umieszczać "diody gaszącej" dla zewnętrznego przekaźnika na samym module - jak to napisałem i pokazałem 3 posty wyżej.
"Dioda gasząca" MUSI być umieszczona pomiędzy 2 kontaktami sterującymi przekaźnika. Trzeba pamiętać, iż ma być spolaryzowana (w stosunku do napięcia na tych kontaktach sterujących) w kierunku zaporowym.
Takie "na wszelki wypadek" umieszczenie diody gaszącej na module (przy równoczesnym jej braku na przekaźniku) powodowało nieprawidłową pracę modułu.
Tak więc należy podłączenie przekaźnika wykonać "zgodnie ze sztuką"!

Drugie "info finalne" to ostateczna postać kodu źródłowego programu sterującego dla "prościutkiego modułu":

// sketch napisany dla modułu ATtiny85
// ==================================================
// Moduł sterujący włączaniem grzanej przedniej szyby
// Bez kontroli warunków (temperatury) i bez uzależnienia czasu grzania szyby
// od tych warunków. Sterowany jedynie zasilaniem samego modułu
// oraz przyciskiem włączenia/wyłączenia grzania.
// ==================================================
// Moduł powinien być zasilany jedynie w stanie dopuszczającym włączenie HWS
// - czyli z uruchomionym silnikiem.
// Przekaźniki HWS1 i HWS2 od włączania grzania połówek szyby powinny być zasilane
// po włączeniu zapłonu a sterowane masą z odpowiednio wyjścia HWS_OUT1 i HWS_OUT2 z modułu.
//
// (c) Tedi_k 2022 - użycie oraz modyfikacje dopuszczone
// pod warunkiem wskazania autora
//

#define RDY_LED 1 // wewnętrzna (w module) kontrolka stanu READY/HWS ON (jak miga)
#define HWS_OUT1 0 // grzana przednia szyba - tanzystor sterujący przekaźnikiem HWS1.
#define HWS_OUT2 2 // tanzystor sterujący przekaźnikiem HWS2
#define HWS_IN 3 // włącznik grzania HWS - sterowanie masą


#define _SW_time 500UL // force_ON wymaga trzymania przełącznika HWS wciśniętego przez 0,5 sekundy
#define _ON_time 330000UL // grzeje przez 330 sekund (5,5 minuty)
#define _BLNK_time 500UL // blink co 0,5 sekundy
#define _HWS1_2_delay 5000UL // Odstęp 5 sekund pomiędzy włączeniem połówek HWS

#define ON true
#define OFF false

#define REL_ON HIGH // sterowanie przekaźnikiem/tranzystorem z portu (wysokim)
#define REL_OFF LOW

#define LED_ON HIGH // dioda-kontrolka sterowana z portu (wysokim)
#define LED_OFF LOW

boolean wrk, WINDSHIELD_H_ON, prev_HWS_IN;
boolean _blnk, wait_SW;
uint32_t _t_ON, _t_BLNK, _t_CAN; // czas (millis()) włączenia trybu force_ON oraz sterowanie miganiem diody

void setup() {
WINDSHIELD_H_ON = wait_SW = false;
_blnk = true;
prev_HWS_IN = HIGH;
pinMode(HWS_OUT1, OUTPUT);
pinMode(HWS_OUT2, OUTPUT);
pinMode(RDY_LED, OUTPUT);
pinMode(HWS_IN, INPUT_PULLUP);

digitalWrite(RDY_LED, LED_OFF); // Wyłączenie LED
digitalWrite(HWS_OUT1, REL_OFF); // Wyłączenie sygnałów HWS1
digitalWrite(HWS_OUT2, REL_OFF); // i HWS2

while (!digitalRead(HWS_IN)); // Przy włączaniu zapłonu przycisk HWS musi być zwolniony (stan niski)
delay(_SW_time);
while (!digitalRead(HWS_IN)); // test zwolnionego przycisku przez 0,5 sek.

_t_BLNK = _t_ON = millis();
}

void loop() {
HWS(WINDSHIELD_H_ON);

if (!WINDSHIELD_H_ON)
digitalWrite(RDY_LED, LED_ON);
else
led_BLNK(); // Przy włączonej HWS kontrolka led miga

wrk = digitalRead(HWS_IN);
if(wrk == LOW && wrk != prev_HWS_IN) { // Klawisz HWS właśnie został naciśnięty
_t_ON = millis();
prev_HWS_IN = LOW;
return;
}

if(wrk == LOW && wrk == prev_HWS_IN && wait_SW)
return; // Czekamy na puszczenie klawisza HWS;

if(wrk == LOW && wrk == prev_HWS_IN) {
if ((uint32_t) (millis() - _t_ON) > _SW_time)
return; // Oczekiwanie na zadany czas utrzymania klawisza wciśniętym
else { // Klawisz wciśnięty odpowiednio długo
if (!wait_SW) // Jeśli jeszcze nie jest obsłużony
WINDSHIELD_H_ON = !WINDSHIELD_H_ON; // to włączenie lub wyłączenie HWS w zależności od jej aktualnego stanu
wait_SW = true; // Klawisz już obsłużony, oczekwanie na jego puszczenie
return;
}
}

if (wrk == HIGH) { // Klawisz puszczony, zezwolenie na ponowną obsługę wciśnięcia klawisza
prev_HWS_IN = HIGH;
wait_SW = false;
return;
}
}

void led_BLNK() {
if ((uint32_t) (millis() - _t_BLNK) > _BLNK_time) {
_t_BLNK = millis();
_blnk = !_blnk;
}
digitalWrite(RDY_LED, _blnk);
}

void HWS(bool on_off) {
if (on_off) {
if (!WINDSHIELD_H_ON) _t_ON = millis();
digitalWrite(HWS_OUT1, REL_ON); // Przekaźnik HWS1 pierwszej połowy
WINDSHIELD_H_ON = ON;
if ((uint32_t) (millis() - _t_ON) > _HWS1_2_delay)
digitalWrite(HWS_OUT2, REL_ON); // Przekaźnik HWS2 drugiej połowy
if ((uint32_t) (millis() - _t_ON) > _ON_time)
WINDSHIELD_H_ON = OFF;
}
else {
digitalWrite(HWS_OUT1, REL_OFF); // Wyłączenie przekaźnika HWS1 pierwszej połowy
digitalWrite(HWS_OUT2, REL_OFF); // Wyłączenie przekaźnika HWS2 drugiej połowy
WINDSHIELD_H_ON = OFF;
}
}

michałek
04-03-2022, 20:46
Jak już skończycie bawić się w przedszkole, to proponuję spróbować projektować płytki drukowane bo patrząc na takie "szkaradziejstwa" jak tu przedstawione to aż dreszcze przechodzą. Ja wiem, odkrycie nowego świata to ekscytacja ale to jak mechanik vs właściciel próbujący wymienić klocki pierwszy raz w życiu, bez narzędzi.
1) Płytki zamawia się np. w PCBway, $5 za 10 sztuk+ok $25 transport + ok 70zł cła/podatki. Przy kilku projektach PCB wychodzi za grosze.
2) Programy do darmowego projektowania amatorskiego są darmo, co pewnie wiecie.
3) Ta zaproponowana przetwornica to ultra szajs. To są takie potworki z których odpadają elementy, te wszystkie płytki mogą nie przetrwać mrozu. Może wiecie może nie, lutowanie bezołowiowe co ma przetrwać mróz to kosztowna sprawa. A te wszystkie arduina i magiczne moduliki itd. to są zlutowane najpodlej w świecie. Bałbym się to do auta wkładać właśnie ze względu na mróz. Rok dwa i elementy zbiera się paznokciem. Samemu jak się lutuje "ołowiem" to jest nie do za... Elementy też mają zakres od -40C albo od 0. Wszystko co tanie jest podłe, nikt tam nie wsadza tych -40C!!!
3) Micros - tanie ale mały wybór. TME drożej ale jak coś sprzedają to jest takie jak piszą.

Taka przetwornica już ujdzie:
https://www.tme.eu/pl/details/amsro-7805-nz/przetwornice-dc-dc/aimtec/

Powodzenia na nowej drodze.

tedi_k
04-03-2022, 22:23
Jak już skończycie bawić się w przedszkole, ....

Serdecznie zapraszamy do zaprezentowania tu "szkoły wyższej".:568:
Nikt nikomu nie broni pokazać "co potrafi".:one:

Poczekamy-zobaczymu co za profesjonalne rozwiązania Kolega zaprezentuje. Tylko prosimy "ze szczegółami" (np. z kodem źródłowym...) - bo to raczej o tym jest ten wątek...

Co do meritum - jaki jest sens produkować płytki dla 2-3 sztuk takich modułów? Wyjaśni to Kolega - w przystępnych słowach - reszcie zainteresowanych?
Bo ja - całkowicie zresztą programowo - najmniejszego sensu nie widzę dla tego typu prac zabierać się za "wyciąganie armaty z powodu tej muchy".

Wtedy, gdy to miało sens (produkowanych było kilkadziesiąt modułów ASSoff) - płytki i owszem były wyprodukowane.
Dla pojedynczego egzemplarza czy 2 sztuk - Kolega może sobie płytki produkować, a ja nadal pozostanę przy swoich uniwersalnych...

Co do jakości użytych elementów - można sobie dobierać dowolnie perfekcyjne. Nikt nikomu nie broni. Od ponad 3 lat jeżdżą w autach takie moduły tylnego światła przeciwmgielnego dla Escape i parę jeszcze podobnych "drobniutkich wynalazków" i jakoś nic się paznokciem nie zdrapało i nasze mrozy nic nie "odmroziły"...:p

Wpis więc bardzo pouczający - czekamy na kontynuację "jak to robi profesjonalista"!:569:

Do dzieła!

michałek
05-03-2022, 07:18
Wpis więc bardzo pouczający - czekamy na kontynuację "jak to robi profesjonalista"!
Dokładnie tego się spodziewałem po Panu, tony bezsensownego sarkazmu. Nadmiaru emotikonek i kolejnej porcji arogancji. Ja nie muszę sobie nic udowadniać a tym bardziej komuś. Chcecie robić druciarstwo lepione na ślinę, wasza sprawa. Sens robienia porządnie, tak by kiedyś jak ktoś to zobaczy nie było wstydu jest zawsze.

Parch
05-03-2022, 08:23
Ale wiesz, że krytyka dla krytyki (żeby się wypowiedzieć tylko) to jest trolling?
Ten temat został założony po to, żeby pokazać, "że można", a Ty się czepiasz nieistotnych (dla idei tematu) "popierdółek". Dlatego dostałeś "ciętą ripostę".
Chcesz udowodnić, że można lepiej, łatwiej, taniej, albo że "też umiesz", to zrób to. Zaprezentuj swoje rozwiązanie - gwarantuję, że na pewno zostanie docenione, jeśli będzie tego warte. Dopuki tego nie dokonasz raczej jednak powinienieś milczeć. Jest to trudne, ale warto spróbować.

michałek
05-03-2022, 08:41
Zaprezentuj swoje rozwiązanie - gwarantuję, że na pewno zostanie docenione, jeśli będzie tego warte. Robiłem to wiele razy. Dwa tematy będą wkrótce również. I nie jest to krytyka dla krytyki, jakbyś przeczytał uważnie: wykazałam moim zdaniem dość poważny problem z takimi rozwiązaniem, podałem też sugestie użyteczne sugestie. Ale każdy czyta to co chce.

Slawko
05-03-2022, 09:08
Projektowanie płytek nie jest jakieś trudne, można, ale czasami lepiej wykorzystać coś co już ktoś stworzył i jest gotowe.

Sami kiedyś wszystko projektowaliśmy i budowaliśmy od podstaw. Dzisiaj nie ma sensu wielu rzeczy robić samemu, szybciej i taniej jest kupić ładnie zrobiony gotowiec jako podzespół, albo podzespoły

Bump: Z drugiej strony szacun dla tych co tworzą. Nie ważne jak, czy ładnie czy z drutami na pająka, ważne że jest materiał wyjściowy. Ten co będzie chciał to sobie przeprojektuje i zrobi po swojemu. Dodatkowo zawsze to jakaś inspiracja i przykłady pewnych rozwiązań które możemy wykorzystać w swoich pracach.

tedi_k
05-03-2022, 16:42
Wygląda na to, iż Kolega michałek odreagował już swoje 'lęki i frustracje'...

Ja... Kolega Tediego?
[....

więc można spróbować wyciągnąć jakiś pożytek z tego co powyżej...

1) Przedstawiane rozwiązania nijak nie są zależne od pomysłu na ich zaadaptowanie do własnej wizji. Czy to na gotowych modułach od Chińczyków z użyciem płytki prototypowej, czy to na tychże modułach umieszczonych na zaprojektowanej we własnym zakresie płytce drukowanej dedykowanej czy też wreszcie na stworzonym we własnym zakresie od podstaw module dedykowanym opartym o wskazany układ ATtiny - działać to będzie dokładnie tak samo. Różnica będzie jedynie w "sprzedażności" rozwiązania oraz cenie jednostkowej. Ja nie robię tych rozwiązań w celach handlowych i do tego robię je jako 'prototypy' - co w oczywisty sposób rzutuje na ich sposób budowy. Mnie to wystarcza i działa u mnie niezawodnie. Każdy może zrobić sobie jak będzie chciał.

2) Poruszone powyżej kwestie niezawodności rozwiązań w warunkach ekstremalnych co do zasady są bezdyskusyjne. Ponieważ jednak w żadnym stopniu nie dyskutujemy o rozwiązaniach "krytycznych dla bezpiecznej eksploatacji samochodu" - niezawodność omawianych rozwiązań w temperaturach około -40st. C wydaje się być co najmniej niekrytyczna... Każdy oczywiście ma prawo zbudować sobie "prosty modulik" odporny na temperatury poniżej -40st. C. Jeśli jest świadom takiej potrzeby - to umie sobie także dobrać stosowną bazę elementową do realizacji tej potrzeby. Cała reszta Koleżeństwa może wierzyć, że "nic złego z takimi modułami w naszych warunkach klimatycznych się nie dzieje".

3) Co do doboru elementów "bazowych" (tu głównie owa "nieszczęsna przetwornica"...) - zawsze można wybrać coś innego. Wybiera się z dostrzeżonych/zauważonych opcji. Ja dostrzegłem taką bo nie patrzyłem na TME. Kolega michałek miał inny, lepszy pomysł (tylko ta "forma" zaprezentowania tego pomysłu... Epitety miały podkreślić trafność wyboru???) . Ponieważ zaproponowana przetwornica ma potrzebne parametry i wygląda na bardziej pasującą do moich potrzeb - to sobie zamówiłem 3 szt. z TME do kolejnych prototypów.

Wnioski - temat nie miał nigdy na celu "namówienia wszystkich do druciarstwa i popeliny". Celem było jedynie pokazanie, iż potrzeby takie jak zgłosił Kolega Barixon dają się realizować relatywnie prostymi metodami. Ponieważ ujawnił się nam tu profesjonalista - to Kolega Barixon ma szansę uzyskać od Kolegi michałek rozwiązanie technicznie poprawne i eleganckie w formie. Pokażcie Panowie w kontakcie ze sobą (a potem zaprezentujcie to ogółowi na forum...), że da się 1szt. takiego modułu zrobić nie na prototypie. Ja tam to skomentuję z całą życzliwością...

Ja nadal pozostanę przy swoich prototypach. Mnie one w zupełności wystarczają i - mimo, że jestem inżynierem ze starych dobrych czasów, gdy oznaczało to jeszcze jakąś wiedzę... - to ich forma prototypowana na płytce prototypowej nijak nie powoduje u mnie "wstydu". Taki był ich zamysł.

Zbigniew_K
06-03-2022, 06:16
Ja tylko podpowiem, że warto gotowe płytki zabezpieczać kilkoma warstwami lakieru ochronnego nieprzewodzącego prąd. Chodzi o ochronę przed utlenianiem i wilgocią.

Pozdrawiam
Z.K.

hindus
07-03-2022, 17:09
To nie jest aż taki duży problem. Mam sterownik nawadniania na działce zrobiony w oparciu o Raspberry, moduł zasilacza, listwa przekaźnikowa. Nawet przewody nie są lutowane tylko osadzone na goldpinach. Po 3 latach jedyne co zaczęło gnić (chociaż dalej działa!) to izolacja kabla USB między modułem zasilacza a RPi. Przez ten czas szlag trafił tylko trafo toroidalne gdzie między zwoje dostała się wilgoć i po kilku minutach pracy "gotując wodę" drut się przegrzał, przetopił izolację i zrobił zwarcie (wywalił bezpiecznik). Od tamtej pory zabieram trafo do domu na zimę :) Ale jeśli o moduły chodzi, to naprawdę nie jest źle z tymi soldermaskami.