Skocz do zawartości
daniel89

Ustawienie pinu jak wyjście HS przy starcie programu

Pomocna odpowiedź

Witam,

Prosze o poradę jak zrobić by przy starcie programu ustawić pin na stan wysoki , bo jak w setup() dodaję ustawienia : pinMode(OUT, OUTPUT);
digitalWrite(OUT,HIGH); , to mi na starcie programu raz mignie wyjście na ułamek sekundy a tego być nie może .

Udostępnij ten post


Link to post
Share on other sites
1 godzinę temu, daniel89 napisał:

Prosze o poradę jak zrobić by przy starcie programu ustawić pin na stan wysoki

Który pin konkretnie, bo zasadniczo, w AVR sprzętowo się nie da. Można skrócić ten czas przez: wyłączenie bootloadera i skrócenie czasu resetu na min (domyślnie w Arduino są chyba 64ms). Inne rozwiązanie rezystor podciągający ale nie z każdym pinem to wyjdzie, np RX jest połączone z mostkiem USB i wiele zależy co on robi po czy w czasie resetu. 

 

Wiele może zależeć też od samej płytki (UNO, Mega, itp) i układów na niej zamontowanych (np mostka USB).

 

Np w ESP8266 nie zapanujesz nad pinami SPI po resecie.

Udostępnij ten post


Link to post
Share on other sites

Zamień kolejność tych dwóch wywołań a przede wszystkim pokaż co tym sterujesz.Przecież od włączenia zasilania do przejęcia sterowania przez funkcję setup() może minąć mnóstwo czasu. To właśnie ten "ułamek sekundy" w którym otoczenie już pracuje a aplikacja procesora jeszcze nie i nic z tym nie zrobisz. Trochę możesz zaoszczędzić wywalając bootloader, ale wtedy płytka przestaje być "Arduino" a zaczyna "AVR", do której potrzebny jest programator ISP.Potem możesz skracać fuse bitami czas przebywania procka w stanie RESET. Najlepszym jednak wyjściem jest modyfikacja sprzętu tak, by zanim program ustawi kierunki i stany na pinie był już stan wysoki.Dlatego musimy wiedzieć co tam podłączasz i jak.

Udostępnij ten post


Link to post
Share on other sites

a nie można przez preprocesor (funkcje przed startem programu) polecenie #define digitalWrite(OUT,HIGH) ? Niestety teraz nie mam jak tego wgrać na płytkę.

W głównej bibliotece Arduino funkcja digitalWrite jest tak wywoływana :

void digitalWrite(uint8_t pin, uint8_t val)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	volatile uint8_t *out;

	if (port == NOT_A_PIN) return;

	// If the pin that support PWM output, we need to turn it off
	// before doing a digital write.
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	out = portOutputRegister(port);

	uint8_t oldSREG = SREG;
	cli();

	if (val == LOW) {
		*out &= ~bit;
	} else {
		*out |= bit;
	}

	SREG = oldSREG;
}

Pytasz co tym robię ? Wystawiam wyjście na zgrzewanie dużej mocy i taki start wywoła iskrę która nie była zamierzona. Dlatego muszę pozbyć się tego a nie przemyślalem że Arduino się tak zachowuje że wystawia na początek stan niski a dopiero w SETUP to zmienia po milisekundzie .

Udostępnij ten post


Link to post
Share on other sites

Użyj pinModeFast i digitalWriteFast (oba są kompilowane na pojedyncze instrukcje procesora).

Ale ja bym to zrobił dając jakiś prosty inwerter na wyjściu przecież wystarczy zwykły tranzystor i parę oporników...

Udostępnij ten post


Link to post
Share on other sites

płytka jest już zrobiona , nic hardwarowo nie mogę zmienić, a dodatkowa płytka to dodatkowe koszta tylko  na tranzystor. 

Może wiecie co robi to co wymyśliłem #define ? Wiem że nadaje stałe wartości przed startem programu, ale nie wiem jak zdefiniować wyjście przed startem by było wysokie przez preprocesor ... można tam #ifdef ,  #if , itp.

Z tym digitalWriteFast , też to jakiś czas zajmuje chociaż widać po opisie bibioteki że mniej : Zwykłe digitalWrite () w rdzeniu Arduino Uno (16 MHz) zajmuje około 6280 nS, podczas gdy manipulacja portem digitalWriteFast () zajmuje 125 nS.

https://github.com/NicksonYap/digitalWriteFast

Mogę spróbować użyć tego Fast , ale teraz nie dam rady jak mówiłem nie mam jak tego sprawdzić. Jeśli ktoś ma pojęcie czy da się w preprocesorze ustawić pin jako wyjście i nadać mu stan wysoki tak by program startował z takimi wartościami to proszę napiszcie będę wdzięczny .

 

.

Udostępnij ten post


Link to post
Share on other sites
1 minutę temu, ethanak napisał:

Użyj pinModeFast i digitalWriteFast (oba są kompilowane na pojedyncze instrukcje procesora).

To jakiś sposób, który przyspieszy przełączenie jest jednak lepszy sposób oparty na avrlibc dzięki któremu można przypisać kod do podsekcji .init . Można spokojnie przypisywać dowolny kod inicjalizacyjny do sekcji od .init5 do .init9 te o niższym indeksie są przeznaczone do inicjalizacji procka. W tym konkretnym przypadku działanie sprowadza się do przełączenia pinu więc można zmienić wcześniej co daje pewność, że procesor wystartuje z ustawionym pinem jednak trzeba użyć do tego nazw rejestrów i pinów z avrlibc a nie funkcji arduino. Jeśli dobrze pamiętam to powinno być coś takiego:

void init_ustawpin() __attribute__ ((naked)) __attribute__ ((section (".init1")));

void init_ustawpin(){

	DDRx |= _BV(PIN);
	PORTx |= _BV(PIN);
}

 

Udostępnij ten post


Link to post
Share on other sites
11 minut temu, daniel89 napisał:

Jeśli ktoś ma pojęcie czy da się w preprocesorze ustawić pin jako wyjście i nadać mu stan wysoki tak by program startował z takimi wartościami to proszę napiszcie będę wdzięczny .

Owszem, mam pojęcie. Nie da się - preprocesor nie do tego służy.

Udostępnij ten post


Link to post
Share on other sites
6 minut temu, ethanak napisał:

Nie da się - preprocesor nie do tego służy.

Arduino nie do tego służy. Procesor służy tak jak mu się rozkaże tylko trzeba użyć odpowiednich argumentów :P

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Czyli nie bardzo rozumiem to jak działa procesor .

To może pytanie do @atMegaTona ,

Jak mam uruchomić te porocedury w SETUP() ?  Pin 7 arduino mam ustawić na wysoki ...

Z tego co czytałem samo uruchomienie SETUP() to już uruchomienie instrukcji procesora , więc to nie zaburzy jakiegoś przypadkowego ustawienia tam stanu niskiego?... no nic później spróbuję to uruchomić , rozumiem że w SETUP() mam wywołać :

init_ustawpin() ? Tylko jak ?

 

Tak to trzeba ustawić ? :

void init_ustawpin() __attribute__ ((naked)) __attribute__ ((section (".init1")));
////////////////////////////////
void init_ustawpin(){
  DDRD |= _BV(7);
  PORTD|= _BV(7);
}
////////////////////////////////
void setup() {
  init_ustawpin();
}

 

Edytowano przez daniel89

Udostępnij ten post


Link to post
Share on other sites

Ta funkcja umieszcza kod na samym początku sekcji pamięci czyli jeszcze przed uruchomieniem czegokolwiek. Nawet przed ustawieniem zmiennych globalnych więc można rzec, że od razu po uruchomieniu, framework arduino jest ładowany dużo później co z resztą sam sprawdziłeś. Dlatego też napisałem, że wszystkie inne "szybkie" inicjalizacje powinny być umieszczone najwcześniej w .section5

8 minut temu, daniel89 napisał:

Z tego co czytałem samo uruchomienie SETUP() to już uruchomienie instrukcji procesora , więc to nie zaburzy jakiegoś przypadkowego ustawienia tam stanu niskiego?... no nic później spróbuję to uruchomić , rozumiem że w SETUP() mam wywołać :

init_ustawpin() ? Tylko jak ? Wywala mi błąd : 'DDRx' was not declared in this scope

Nie w setup() tylko wcześniej. Zaraz po zainkludowaniu io. Setup() to część arduino. Nic dziwnego, że "not declared" bo za ten 'x' trzeba wpisać poprawną literę portu np. B czy C a pod PIN poprawny pin np; PB0. Nie ma innego sposobu, żeby włączyć pin wcześniej niż przypisując go do sekcji .init a arduino tego nie umożliwia.

Udostępnij ten post


Link to post
Share on other sites
(edytowany)


Czyli tak ustawiam to przed void setup() ?

void init_ustawpin() __attribute__ ((naked)) __attribute__ ((section (".init1")));

void init_ustawpin(){
  DDRD |= _BV(PD7);
  PORTD|= _BV(PD7);
}
///////////////////////////////////////////////////////////////////////////////////////
void setup() {}

Wiesz w Arduino zwykle miałem styczność tylko z tym co się wykonywało od void setup(), dlatego nie bardzo rozumiałem jak to ma działać . Teraz ta procedura init_ustawpin() zostanie wywołana i przejdzie do skecji .init1 ustawieć procesora i tam podpisze portd pin 7 na stan wysoki przed startem programu czyli wywoałniem setup() dla arduino ??

Teraz nie musze w setup() tego ustawiać i będzie działać ? , rozumiem że tego już nie muszę dodawać bo wcześniej to ustawiłem tym co podałeś ?

void setup() {
digitalWrite(7,HIGH);
pinMode(7, OUTPUT);
}

 

Edytowano przez daniel89

Udostępnij ten post


Link to post
Share on other sites
38 minut temu, atMegaTona napisał:

Procesor służy tak jak mu się rozkaże

Ale wiesz o tym,  że procesor i preprocesor to dwie różne rzeczy?

 

Udostępnij ten post


Link to post
Share on other sites

A ja bym proponował wrócić do tego co napisał @marek1707 Po pierwsze kod szkicu nie jest uruchamiany jako pierwszy - najpierw musi się uruchomić bootloader. Po drugie samo uruchomienie mikrokontrolera zajmuje sporo czasu - więc nawet gdyby zrezygnować z bootloadera, a pierwszą instrukcją asemblera było ustawienie pinu to i tak na wyjściu pojawi się całkiem spory impuls. Na to może pomóc tylko sprzęt - być może tak prosty jak jeden rezystor, a może będzie potrzebny negator.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
1 godzinę temu, atMegaTona napisał:

To jakiś sposób, który przyspieszy przełączenie jest jednak lepszy sposób oparty na avrlibc dzięki któremu można przypisać kod do podsekcji .init . Można spokojnie przypisywać dowolny kod inicjalizacyjny do sekcji od .init5 do .init9 te o niższym indeksie są przeznaczone do inicjalizacji procka.

Dobrze kombinujesz  ale można to jeszcze przyspieszyć umieszczając w init0 czy 1 pamiętając, że R1 nie ma (może nie mieć) wartości 0 i jeśli będzie potrzeba trzeba w ASM zrobić wstawkę np XOR r1,r1. W .init3 R1 już == 0 ale wcześniej wykona się parę rozkazów. Co dokładnie robią init?

.init0:
Jeśli ją zdefiniujemy wykona się zaraz po resecie (wektor pod adresem 0).
.init1:
Niezdefiniowana, dla użytkownika.
.init2:
Używana przez C, zeruje R1 i SREG, inicjalizuje stos:
0000008c <__ctors_end>:
8c: 11 24 eor r1, r1
8e: 1f be out 0x3f, r1 ; 63
90: cf ef ldi r28, 0xFF ; 255
92: d0 e1 ldi r29, 0x10 ; 16
94: de bf out 0x3e, r29 ; 62
96: cd bf out 0x3d, r28 ; 61
  
.init3:
Niezdefiniowana, dla użytkownika. Od tej sekcji bezpiecznie jest umieszczać kod w C, ponieważ
R1 i stos jest już zainicjalizowany.
.init4:
Zeruje sekcję /bss oraz kopiuje wartości przypisane zmiennym z pamięci flash do ram.
0000009c <__do_copy_data>:
9c: 11 e0 ldi r17, 0x01 ; 1
9e: a0 e0 ldi r26, 0x00 ; 0
a0: b1 e0 ldi r27, 0x01 ; 1
a2: ea ec ldi r30, 0xCA ; 202
a4: f0 e0 ldi r31, 0x00 ; 0
a6: 00 e0 ldi r16, 0x00 ; 0
a8: 0b bf out 0x3b, r16 ; 59
aa: 02 c0 rjmp .+4 ; 0xb0 <__do_copy_data+0x14>
ac: 07 90 elpm r0, Z+
ae: 0d 92 st X+, r0
b0: a0 30 cpi r26, 0x00 ; 0
b2: b1 07 cpc r27, r17
b4: d9 f7 brne .-10 ; 0xac <__do_copy_data+0x10>
Dla mikrokontrolerów z pamięcią programu większą niż 64kB przy kopiowaniu sekcji .data dba o
odpowiednie ustawienie rejestru PAMPZ.
.init5:
Niezdefiniowana, dla użytkownika.
.init6:
Niezdefiniowana w C, używana w C++.
.init7:
Niezdefiniowana, dla użytkownika.
.init8:
Niezdefiniowana, dla użytkownika.
.init9:
Skok do main():
b6: 0e 94 61 00 call 0xc2 ; 0xc2 <main>
ba: 0c 94 63 00 jmp 0xc6 ; 0xc6 <_exit>
000000be <__bad_interrupt>:
be: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
000000c2 <main>

Jest jeszcze .fini

.finit9:
Nie używany. definiowanych przez użytkownika. Tu nastąpi skok po wykonaniu exit ().
.fini8:
Nie używany. definiowanych przez użytkownika.
.fini7:
Nie używany. definiowanych przez użytkownika.
.fini6:
Niewykorzystane dla programów w C, ale wykorzystywane do destruktorów w programach C ++.
.fini5:
Nie używany. definiowanych przez użytkownika.
.fini4:
Nie używany. definiowanych przez użytkownika.
.fini3:
Nie używany. definiowanych przez użytkownika.
.fini2:
Nie używany. definiowanych przez użytkownika.
.fini1:
Nie używany. definiowanych przez użytkownika.
.fini0:
Przechodzi w nieskończoną pętlę po zakończeniu programu.
000000ca <_exit>:
ca: f8 94 cli
000000cc <__stop_program>:
cc: ff cf rjmp .-2 ; 0xcc <__stop_program>

ale w Arduino nigdy się nie wykona, bo wyjście z loop powoduje ponowny skok do niego bo loop() znajduje się w wiecznej pętli (może razem z setup? Nie pamiętam).

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...