Skocz do zawartości

Pomocna odpowiedź

Napisano

Dzień dobry. Potrzebuje pomocy w napisaniu , zmodyfikowaniu kodu na Arduino. Z maszyny idzie lin o prędkości 19200, przepuszczam ten sygnał przez MCP2003 dalej do Atmel M328P. Docelowo atmel po wykryciu danych ramek steruje 5 mosfetami. Problem w tym, że kod nie czyta mi całego linu, mam wrażenie, że system się zapycha, ramki które wpadają wolniej jako tako działają, ramki które idą szybciej umykają . W moim kodzie użyta jest funkcji delay - to jest pewnie przyczyną. Niestety moja wiedza się skończyła i chcę poprosić o pomoc kogoś kto to przerabiał ( oczywiście odpłatnie )

(edytowany)

Cóż, kod jest tajemnicą, więc nie wiemy o co chodzi. Może odbierasz ramki alokując nowy bufor za każdym razem, do tego wolna funkcja przetwarzająca i taki efekt przy szybszej transmisji. Być może używasz innych funkcji blokujących, nawet o tym nie wiedząc. Nie jestem programistą, ale w ostatnim czasie kombinuję w temacie "okołouartowym". Przy przetwarzaniu ramek trzeba wykluczyć wszystkie zamulacze, dać odpowiedni rozmiar buforów tx/rx, najlepiej alokowanych raz lub gdzieś na początku funkcji, przed pętlą przetwarzającą dane. Inaczej procesor zajedzie się, pojawią się przekłamania w transmisji. Esp32 wybacza więcej amatorskich błędów (mam na myśli siebie).

Edytowano przez orb777

@orb777 tyle że ESP32 ma nieco szybszy zegarek, w ch... ramu. A gdyby wątkotwórca pokazał kod to może by się obyło bez płacenia... ale jak się uparł to niech któryś z naszych gimnazjalistów zarobi.

(edytowany)

wklejam kod. Pozdrawiam

 

#define LIN_SPEED 19200 // Standardowo 9600, 10400, 19200

uint8_t sync;

uint8_t LIN_data[10];
uint8_t LIN_data_i=0;

uint8_t mosfet_pin[5] = {6, 7, 8, 9, 10};
uint8_t led_pin = 14;
uint8_t cs_pin = 3;
uint8_t wake_pin = 2;
void setup() {
  //Serial.begin(115200);   // Monitor szeregowy do debugowania
  Serial.begin(LIN_SPEED); 

  digitalWrite(0, HIGH);

  pinMode(cs_pin, OUTPUT);
  digitalWrite(cs_pin, HIGH);

  pinMode(wake_pin, OUTPUT);
  digitalWrite(wake_pin, HIGH);
  
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, LOW);

  for(uint8_t i = 0; i < 5; i++)
  {
    pinMode(mosfet_pin[i], OUTPUT);
    digitalWrite(mosfet_pin[i], LOW);
  }

}

void loop() 
{
  
  // W standardowym UART sygnał BREAK generuje błąd ramkowania lub odczytuje się jako 0x00.
  if (Serial.available()) 
  {
    if (Serial.peek() == 0x00) 
    {
        Serial.read(); // Usuń bajt BREAK z bufora
      
        // 2. Synchronizacja (zawsze 0x55)
        while (!Serial.available());
        sync = Serial.read();
      
        if (sync == 0x55) 
        {
          toggle_led();
          // 3. Odczyt Protected Identifier (PID)
          while (!Serial.available());
          uint8_t pid = Serial.read();
          uint8_t id = pid & 0x3F; // ID to pierwsze 6 bitów

  
          // 4. Odczyt danych (zazwyczaj od 1 do 8 bajtów)
          // Uwaga: W prawdziwym LIN długość zależy od ID. Tutaj czytamy co jest w buforze.
          delay(10); // Czas na dopłynięcie reszty ramki
          while (Serial.available()) 
          {
            LIN_data[LIN_data_i++] = Serial.read();
          }
          /*
          Serial.print("ID: 0x");
          Serial.print(id, HEX);
          Serial.print(" | Dane: ");
          for(uint8_t i =0; i <LIN_data_i;i++)
          {
            Serial.print(arr[i], HEX);
            Serial.print(" ");
          }*/
          if(id == 0x0A)
          {
              if(LIN_data[1] == 0x56)
              {
                mosfet_enable(1);
              }
              else
              {
                mosfet_disable(1);
              }
          }
          if(id == 0x0C)
          {
            if(LIN_data[0] == 0x12)
            {
              mosfet_enable(2);
            }
            else
            {
              mosfet_disable(2);
            }
          }
          

          LIN_data_i=0;

          //Serial.println();
        }
    } 
    else 
    {
      // Jeśli to nie BREAK, wyczyść śmieci
      Serial.read();
    }
  }
}

void mosfet_enable(uint8_t v)
{
  if(v >= 1 && v <= 5)
  {
    digitalWrite(mosfet_pin[v-1], HIGH);
  }
}

void mosfet_disable(uint8_t v)
{
  if(v >= 1 && v <= 5)
  {
    digitalWrite(mosfet_pin[v-1], LOW);
  }
}

  void toggle_led(void)
  {
    digitalWrite(led_pin, !digitalRead(led_pin));
  }

 

Edytowano przez tomasz_bik

@ethanak czuje, że szukam winy w kodzie a może okazać się ,że winny jest zbyt słaby procek. Poczekam jeszcze chwilę, może któryś z kolegów na coś wpadnie. W dalszej kolejności skupię się na wymianie proca na ESP32

1 godzinę temu, tomasz_bik napisał:

winny jest zbyt słaby procek

Jeśli chodzi o moc obliczeniową, to do takiego zadania każdy procesor jest wystarczająco mocny.

Proponuję, przynajmniej na początku, użyć gotowej biblioteki ( np. coś takiego). Możesz też porównać swój kod z kodem biblioteki, aby wychwycić ewentualne błędy.

2 godziny temu, tomasz_bik napisał:

W dalszej kolejności skupię się na wymianie proca na ESP32

Jak tam nawtykasz delayów to będziesz miał ten sam efekt co do tej pory, tyle że będzie nowocześniej wyglądać. Najszybszy procesor nie pomoże na błędny kod.

 

6 godzin temu, tomasz_bik napisał:
if (Serial.peek() == 0x00) 

W pakiecie zawsze jedynym 0x0 jest break?

 

6 godzin temu, tomasz_bik napisał:
while (Serial.available()) 
          {
            LIN_data[LIN_data_i++] = Serial.read();
          }

A co jeśli pojawi się więcej "danych", choćby przez zakłócenia na linii?

1 minutę temu, orb777 napisał:

W pakiecie zawsze jedynym 0x0 jest break?

Uhm... z tego co pamiętam LIN ma CRC, więc raczej nie jedynym 😉 

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...