Skocz do zawartości

ATTiny 1-Series - Zegarek na baterię CR2023


Pomocna odpowiedź

10 godzin temu, pmochocki napisał:

Jestem ciekaw ile osób z tego forum bawiło się takim lub podobnym LCD sterując każdy segment samodzielnie...

@pmochocki Ja się bawiłem 🙂 z tą płytką i przyznam, że trochę mi to czasu zajęło ale się udało. Pobór prądu z aktywnym LCD ~20uA. Kod zajmuje jakieś 4kB bez optymalizacji z optymalizacją coś chyba z 3,5kB. W Cosmic bool zajmuje jeden bit i można odnieść się bezpośrednio do każdego bitu bez liczenia masek.

Link to post
Share on other sites
(edytowany)
Dnia 6.11.2021 o 09:38, slon napisał:

Ja się bawiłem 🙂 z tą płytką

Dzięki! Od razu rzucił mi się w oczy pewien aspekt, którego u siebie też się obawiam - dokładność. Częstotliwość generowaną przez kwarc należałoby sprawdzić. Potem można ją skorygować kondensatorami, ale to jest upierdliwe podeście. Doczytałem natomiast, że ATTiny seria 2 i ATMega seria 0 mają dodatkowy rejestr, który umożliwia kalibrację RTC. Wrócimy do tego jak opracuję jakąś metodologię kalibracji... 

Edytowano przez pmochocki
Link to post
Share on other sites

W stm8L jest możliwość wyprowadzenia zegara RTC bezpośrednio na pin. W zależności o wersji procka jest to 1Hz lub bodajże 512Hz. Można więc sprawdzić jak blisko jesteśmy względem oczekiwanej wartości i zrobić ewentualną kalibrację. Zgodnie z notą od ST RTC można skalibrować z dokładnością do 1ppm. Nowych procków AVR puki co nie posiadam więc nie sprawdzałem w dokumentacji jakie są możliwości.

  • Lubię! 1
Link to post
Share on other sites

Mikrokontrolera, który obsłużyłby mój moduł z e-papierem, jeszcze nie mam. Wyświetlacz LCD powoli płynie sobie z Chin. Postanowiłem więc skupić się na precyzji pomiaru czasu. W sumie odmierzanie czasu to główny cel zegarka, więc chyba warto poświęcić temu zagadnieniu chociaż chwilkę. Mogę zmieniać pojemność kondensatorów przy kwarcu zegarkowym i/lub zakupić ATTiny z serii 2, gdzie kalibrację mógłbym przeprowadzić programowo. W procedurze przerwania RTC_PIT_vect zmieniam stan pinu i mogę zmierzyć jaka częstotliwość jest generowana. No dobra, ale czym mierzyć tą częstotliwość precyzyjnie??? Kupić oscyloskop czy miernik częstotliwości?

Ja planuje użyć do tego swojego Arduino UNO. Zmierzę ile tyknięć zegara uzbieram przez jedną sekundę. Czy liczę, że moje Ardunino ma jakiś super dokładny kwarc 16MHz. No nie... raczej nie ma. Przydałaby się jakiś wzorzec metra, a dokładnie mówiąc jakaś częstotliwość wzorcowa. Przez chwilkę rozważałem DCF77 , jednak obecnie zakłócenia są tak duże, że system się nie sprawdza: Zakłócenia radiowe rozregulowały zegar ratusza w Gdańsku . Rozważałem też NTP , jednak ostatecznie zdecydowałem się na użycie powszechnie dostępnych drogą radiową zegarów atomowych i rubidowych. Mój moduł GPS ma wyprowadzony sygnał PPS , który będzie moją częstotliwością wzorcową. Wystarczy, że porównam ilość tyknięć zegara zebranych w czasie jednej sekundy z mojego zegarka ATTiny i porównam z jedną sekundą z modułu GPS. Oczywiście po tym jak GPS złapie sygnał.

Moduł dotarł do mnie w tym tygodniu i wreszcie dziś znalazłem chwilkę aby go przetestować. Wygląda, że wszystko działa zgodnie z oczekiwaniem:

image.thumb.png.7289403ec62b728e2857db824cea2b59.pngimage.thumb.png.e494d7d27f62453652abc12149f51a3d.pngIMG_20211113_235759.thumb.jpg.ea599992ade1febd96094a32375acad7.jpg 

Teraz trzeba zabrać się za programowanie Arduino UNO. 

Jeśli ktoś uważa, że ten pomysł jest bez sensu, bo jest inny: lepszy, dokładniejszy, tańszy lub po prostu inny... to chętnie przyjmę słowa krytyki na klatę i się czegoś nauczę.

Link to post
Share on other sites
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)

Tym razem szybki wpis opisujący jak zmarnowałem dwie godziny. Zaprogramowałem swoje Arduino UNO, aby za pomocą ICP mierzyć długość impulsu. Jednak rejestr ICR1H cały czas był zerowy. Wszystko sprawdzałem po 100 razy i wszystko wyglądało poprawnie. Aż coś mnie tknęło aby sprawdzić co dzieje się pod płaszczykiem Arduino. Zanim wywołane zostaną funkcje setup() i loop() wołana jest funkcja init(). Oto jej wersja z \hardware\arduino\avr\cores\arduino\wiring.c:

void init()
{
	// this needs to be called before setup() or some functions won't
	// work there
	sei();

[...]

	// put timer 1 in 8-bit phase correct pwm mode
#if defined(TCCR1A) && defined(WGM10)
	sbi(TCCR1A, WGM10);
#endif
  
[...]

}

Licznik był ustawiany w tryb 8-bit. Pora iść spać. Może jutro uda się opisać coś ciekawszego 🙂 

Edytowano przez pmochocki
Link to post
Share on other sites
(edytowany)

Ostatnio nie miałem zbyt dużo czasu. Stwierdziłem więc, że pora zarwać nockę, aby pchnąć projekt trochę do przodu.

Dnia 14.11.2021 o 00:10, pmochocki napisał:

Ja planuje użyć do tego swojego Arduino UNO. Zmierzę ile tyknięć zegara uzbieram przez jedną sekundę. Czy liczę, że moje Ardunino ma jakiś super dokładny kwarc 16MHz. No nie... raczej nie ma. Przydałaby się jakiś wzorzec metra, a dokładnie mówiąc jakaś częstotliwość wzorcowa. Przez chwilkę rozważałem DCF77 , jednak obecnie zakłócenia są tak duże, że system się nie sprawdza: Zakłócenia radiowe rozregulowały zegar ratusza w Gdańsku . Rozważałem też NTP , jednak ostatecznie zdecydowałem się na użycie powszechnie dostępnych drogą radiową zegarów atomowych i rubidowych. Mój moduł GPS ma wyprowadzony sygnał PPS , który będzie moją częstotliwością wzorcową. Wystarczy, że porównam ilość tyknięć zegara zebranych w czasie jednej sekundy z mojego zegarka ATTiny i porównam z jedną sekundą z modułu GPS. Oczywiście po tym jak GPS złapie sygnał.

Arduino UNO przygotowane do pomiarów. Jutro jeszcze świeżym okiem przejrzę kod przed publikacją, ale już dziś wyniki pomiarów PPS z mojego modułu GPS:

Let us start......
Measurement in progress............
Measurement finished!

Overflow Count: 243
Ticks Count: 64948


Let us start........
Measurement in progress............
Measurement finished!

Overflow Count: 243
Ticks Count: 64950


Let us start.............
Measurement in progress............
Measurement finished!

Overflow Count: 243
Ticks Count: 64949


Let us start......
Measurement in progress............
Measurement finished!

Overflow Count: 243
Ticks Count: 64939


Let us start.........
Measurement in progress............
Measurement finished!

Overflow Count: 243
Ticks Count: 64951


Let us start...........
Measurement in progress............
Measurement finished!

Overflow Count: 243
Ticks Count: 64942

Rozrzut do 12 tyknięć zegara 16MHz. Muszę zebrać większą próbkę i skorelować z rozrzut z ilością satelit widzianych przez moduł GPS... lub po prostu założyć, że jest dobrze i zabrać się za dalsze programowanie zegarka 🙂

 

Edytowano przez pmochocki
Link to post
Share on other sites

Jednak ilość satelit i czas, który moduł GPS potrzebuje na ustabilizowanie swojego zegara, odgrywa dość ważną rolę. Wygląda na to, że kwarc w moim module GPS się "późni". Po odnalezieniu satelit, długość sygnału PPS cały czas maleje by po kilku minutach dać bardzo stabilną długość impulsu. 

Doświadczenie jeszcze raz pokazało, że warto po kilku dniach spojrzeć jeszcze raz na swój kod krytycznym okiem - mały babol się znalazł.
Kod można obejrzeć na Githubie: https://github.com/pmochocki/precise_1s_pulse_width/blob/main/UNO_pulse_with.ino lub poniżej.

Po ustabilizowaniu się modułu GPS zebrałem 1000 próbek. W Arduino UNO mam kwarc 16MHz i na the 16 milionów tyknięć, przy próbie wynoszącej 1000 odchylenie standardowe wyszło poniżej 9. Ja jestem z tego wyniku bardzo zadowolony. W następnym "odcinku" podłączam swój "zegarek" i rozpoczynam kalibrację.

/*
MIT License
Copyright (c) 2021 Piotr Mochocki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include <avr\io.h>
#include <avr\interrupt.h>

#define VERBOSE 0         // How verbose to be on the serial output. Set to 0 when collecting bulk data.
#define LOOP 1            // One time measurment or repeat in loop forever. Set to 1 when collecting bulk data.
#define NOISE_CANCELER 0  // Set to 1 to enable Input Capture Noise Canceler

volatile uint16_t timestamp;          // Set in timer capture interrupt.
volatile uint16_t overflowCount;      // Incremented in timer overflow interrupt. 
                                      // Cleared in main loop. (STATE_INIT_MEASURMENT)
volatile uint16_t overflowCountAtICR; // Set in timer capture interrupt based on overflowCount.

typedef enum : uint8_t {   
   STATE_INIT_MEASURMENT,
   STATE_WAIT_FOR_MEASURMENT, 
   STATE_BEGIN_MEASURMENT, 
   STATE_MEASURMENT,
   STATE_END_MEASURMENT, 
   STATE_POST_MEASURMENT} state;      // The state machine. The state names are self-explanatory. :)

volatile state currentState;

ISR(TIMER1_OVF_vect)
{
  overflowCount++;
}

ISR(TIMER1_CAPT_vect)
{
  timestamp = ICR1;
  overflowCountAtICR = overflowCount; 
  currentState = currentState + 1;    //Keep it short and simple :)
}

void timer_init()
{
  TCCR1A = 0;                       // Needed because in the init() function arduino puts the timer1 in 8-bit phase correct pwm mode
  TCCR1B = (1<<CS10)| (1<<ICES1);   // Prescaler set to 1 and enable trigger by rising edge
  if(NOISE_CANCELER)
    TCCR1B |= (1<<ICNC1);           // Enable Input Capture Noise Canceler if requred
  TIMSK1= (1<<ICIE1) | (1<<TOIE1);  // Enable ICP i overflow interrupts
}

void setup() {
  pinMode(8, INPUT);
  Serial.begin(250000);             // Remember to adjut the serial bound rate
  currentState = STATE_INIT_MEASURMENT;
  timer_init();
}

void loop() {
  // Names are self-explanatory. Volatile is requred - gcc will optimise to much without it
  volatile uint16_t overflowCountAtBeginning; 
  volatile uint16_t overflowCountAtEnd;
  volatile uint16_t timestampAtBeginning;
  volatile uint16_t timestampAtEnd; 
  
  if(currentState == STATE_INIT_MEASURMENT) {
    if(VERBOSE)
      Serial.print("Let us start...");
    overflowCount = 0;
    currentState = STATE_WAIT_FOR_MEASURMENT;
  } 
  else if(currentState == STATE_WAIT_FOR_MEASURMENT) {
    if(VERBOSE)
      Serial.print(".");
  }
  // Collect data at the begining of the pulse 
  else if(currentState == STATE_BEGIN_MEASURMENT) {
    overflowCountAtBeginning = overflowCountAtICR;
    timestampAtBeginning = timestamp;
    currentState = STATE_MEASURMENT;
    if(VERBOSE) {
      Serial.println("");
      Serial.print("Measurement in progress...");
    }
  }
  else if(currentState == STATE_MEASURMENT) {
    if(VERBOSE)    
      Serial.print(".");
  }
  // Collect data at the end of the pulse 
  else if(currentState == STATE_END_MEASURMENT) {
    overflowCountAtEnd = overflowCountAtICR;
    timestampAtEnd = timestamp;
    if(VERBOSE) {
      Serial.println("");
      Serial.println("Measurement finished!");   
    }   
    // Calculate the "pulse length"
    uint16_t overflowCountMeasured = overflowCountAtEnd - overflowCountAtBeginning;
    uint16_t ticksMeasured = timestampAtEnd - timestampAtBeginning;
    
    // If the timestamp is bigger at the begining then at the and we need to ajust 
    // As a reminder (ISO/IEC 9899:1999 (E) §6.2.5/9):
    // A computation involving unsigned operands can never overflow, because a result
    // that cannot be represented by the resulting unsigned integer type is reduced 
    // modulo the number that is one greater than the largest value that can be 
    // represented by the resulting type. 
    //
    // (unsigned)0 - (unsigned)1 equals -1 modulo UINT_MAX+1, or in other words, UINT_MAX
    // Remeber to supstract 1 :)
    if( timestampAtBeginning > timestampAtEnd ){
      overflowCountMeasured--;
      ticksMeasured--;
    }
    
    if(VERBOSE) {
      Serial.println("");
      Serial.print("Overflow Count: ");
      Serial.println(overflowCountMeasured);
      Serial.print("Ticks Count: ");
      Serial.println(ticksMeasured);
      Serial.println("");
      Serial.println("");
    }
    else {
      Serial.println(ticksMeasured);
    }
    currentState = STATE_POST_MEASURMENT;
  }
  else if(currentState >= STATE_POST_MEASURMENT){
    if(LOOP)  
      currentState = STATE_INIT_MEASURMENT;
    else
      currentState = STATE_POST_MEASURMENT;
  }
  delay(100);
}

 

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!

Anonim
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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.