logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak zaimplementować buforowanie danych w RAM na STM32L031?

korteksik 03 Maj 2020 00:24 732 3
REKLAMA
  • #1 18664682
    korteksik
    Poziom 10  
    Prosze o poradę jak podejść do tematu.. Sprawa ma się tak:
    Buduję system, w którym jest moduł "czujnika" zrobiony na stm32l031 + RFM69 oraz Gateway które ze sobą się komunikują. Czujnik ma za zadanie zmierzyć napięcie, wygenerować z RTC aktualny czas pomiaru i wysłać go do Gatewaya,
    który po otrzymaniu danych wysyła potwierdzenie do modułu. W razie nie otrzymania potwierdzenia, czujnik ponawia wysyłkę danych - i tak do 10 razy. Jeśli po 10 próbach się nie uda, to pomiar jest tracony. I to działa.
    A teraz chciałbym dodać taką funkcjonalność, że jeśli moduł nie dostanie potwierdzenia, to żeby zapisywał pomiar w RAM. Przy kolejnym pomiarze moduł wyśle aktualny pomiar oraz ten z pamięci RAM, którego nie udało się wysłać
    poprzednim razem. Dane jakie wysyłam to timestamp 4 bajtowy oraz napięcie jako 2 bajty. Bufor FIFO w RFM69 ma wielkość 66 bajtów, więc pomiarów mogę wysłać 10 i zostaje jeszcze 6 bajtów na np. informacje ile danych archiwalnych zawiera paczka itp.
    Docelowo chciałbym przechowywać w RAM do 50 pomiarów.
    Myślałem o zrobieniu dwóch 50 elementowych tablic - jednej z elementami 4 bajtowymi, drugiej 2 bajtowymi i w nich przechowywać pomiary,ale nie bardzo mam pomysł jak później to obsługiwać. Bo załóżmy, że w tablicach
    przechowuję 15 pomiarów i przy kolejnej próbie udało mi się wysłać aktualny pomiar i 9 zarchwizowanych ( w sumie 10 pomiarów). Pozostaje 6 archiwalnych które muszę przeindeksować (bo z 15 zostało 6) czyli przepisać komórka po komórce:
    pomiar z indeksem 10 do indeksu 0, 11->1 i tak dalej.
    Gdyby zaś nie udało by się wysłac danych, to trzeba ten pomiar dodać do tablic i tez przeindeksować archiwalne pomiary zwiększając każdy o 1.
    Mam nadzieję, że zrozumiale to opisałem.
    A czy nie da się tego zrobić prościej?
  • REKLAMA
  • #2 18664769
    rb401
    Poziom 39  
    korteksik napisał:
    A czy nie da się tego zrobić prościej?


    Prościej by było użyć filozofii bufora kołowego. Czyli tablicy elementów (u Ciebie sześciobajtowych) i dwóch wskaźników (nie koniecznie rozumianych jako adres fizyczny, bo może być to indeks w tablicy) "głowy" i "ogona" danych do wysyłki. Wtedy w operacjach zapisu i odczytu z bufora odpowiednio interpretujesz i przeliczasz te wskaźniki, używając zawijania ich w kółko (modulo) na tym buforze. Nie musisz tych zmiennych przekładać z miejsca na miejsce i zawsze masz je w określonej kolejności w ciągłym obszarze (który czasami jest "zawinięty").

    Istnieje nawet mnóstwo gotowych realizacji takich buforów kołowych o różnym stopniu funkcjonalności (też w bibliotekach standardowych C++), pozwalające na realizację buforów FIFO, LIFO i różnych mieszanych.

    Tak w uproszczeniu, to mógłbyś użyć bufora LIFO, gdzie nowe pomiary władasz do bufora od strony "głowy", a do wysyłki też pobierasz od strony głowy w porcjach do max. 10 sztuk na jedno wysłanie.
    A w przypadku zapisu nowego pomiaru do bufora, jeśli bufor jest pełny (sytuacja awaryjna) to przed dopisaniem pomiaru, usuwasz (na śmietnik) jeden element od strony ogona bo jest najstarszy.
    Jedyny problem jaki widzę, który może komplikować użycie gotowych algorytmów, byłby związany z tym że pobierając serię danych do wysyłki (do FIFO RFM) nie masz pewności że można zwolnić miejsce w którym były w buforze, aż dopiero jak przyjdzie potwierdzenie. A zwykle gotowe implementacje buforów kołowych, łączą w jedno odczyt i modyfikację wskaźników (czyli inaczej mówiąc zwalniają miejsce po odczytanych danych).
  • REKLAMA
  • #3 18664925
    BlueDraco
    Specjalista - Mikrokontrolery
    Bufor cykliczny o nieco zmodyfikowanej funkcjonalności:
    - Nowy element można dodać zawsze; jeśli bufor jest pełny, zamazujemy najstarszy.
    - Oddzielone funkcje odczytu n elementów i usuwania z bufora - czytamy nie usuwając, następnie usuwamy oddzielnym wywołaniem. Tu trzeba uważać na synchronizację, bo nie będzie dobrze, jeśli pomiędzy odczytem i usunięciem coś się nam do bufora dopisze. Można to rozwiązać przez wprowadzenie trzeciego wskaźnika - na pierwszy element nieprzeczytany. Wtedy funkcja usuwania usuwa od aktualnego wskaźnika "ogona" (który mógł się zmienić po odczycie) do wskaźnika ostatniego przeczytanego.

    Stempel czasowy z RTC to niekoniecznie dobry pomysł - zegar serwera jest bardziej wiarygodny od zegara czujnika.
  • #4 18666054
    korteksik
    Poziom 10  
    BlueDraco napisał:
    Bufor cykliczny o nieco zmodyfikowanej funkcjonalności:
    - Nowy element można dodać zawsze; jeśli bufor jest pełny, zamazujemy najstarszy.
    - Oddzielone funkcje odczytu n elementów i usuwania z bufora - czytamy nie usuwając, następnie usuwamy oddzielnym wywołaniem. Tu trzeba uważać na synchronizację, bo nie będzie dobrze, jeśli pomiędzy odczytem i usunięciem coś się nam do bufora dopisze. Można to rozwiązać przez wprowadzenie trzeciego wskaźnika - na pierwszy element nieprzeczytany. Wtedy funkcja usuwania usuwa od aktualnego wskaźnika "ogona" (który mógł się zmienić po odczycie) do wskaźnika ostatniego przeczytanego.



    Miałem nadzieję, że będzie to jednak prostsze :cry:
    No cóż, trzeba zakasać rękawy i brać się do roboty :idea:

    BlueDraco napisał:

    Stempel czasowy z RTC to niekoniecznie dobry pomysł - zegar serwera jest bardziej wiarygodny od zegara czujnika.


    Tak wiem, ale chodzi o informację z jakiego czasookresu pochodzą dane, bez znaczenia jest nawet minutowa różnica.
REKLAMA