Comandare ventola PWM con LIN BUS

Non pensavo ai disturbi perchè le prove le faccio a motore spento e i 12v dell'auto sono da batteria quindi stabili.
Pensavo più alla resistenza di pullup che ho messo sul segnale di ingresso perchè Arduino Due ha il processore a 3.3v. Può essere che cambiando l'alimentazione dai 5v dell'USB ai 12v dell'auto devo modificare la resistenza?

Se metti lo schema sappiamo di cosa stiamo parlando
Comunque il programma che hai postato è fallato, come programma
E stai andando nella direzione sbagliata, come concetto
Adesso sono sul lavoro, stasera ti spiego...

Grazie Nelson,
aspetto le tue spiegazioni.
Di seguito lo schema:

Schema MCP2004.JPG

Dopo una giornata in ditta col condizionatore guasto e due ore dal medico in 30 in sala d'attesa mi sono preso il colpo della strega con l'aria condizionata a casa; se sarò quindi un po' brusco mi sopporterai.....
la prima cosa che ho notato nel tuo programma attuale è che hai dimensionato 47 comandi ma l'array di lunghezze è lungo solo 5; dovrebbe, anzi "deve" avere la stessa lunghezza della prima dimensione dell'array dei comandi, messo così come lo hai messo tu il programma se va lo fa solo per fortuna
per seconda cosa, 47 comandi per solo 2 ventole a tre velocità (5 contando "fermo" e "massimo") sono troppi, non è la strada giusta
Allora ho cercato il datasheet del chip mcp2004: è poco più di un puro convertitore di livello, dal 12 V del LIN bus alla tensione di lavoro dell'arduino, non interpreta i dati, ne fa sincronizzazione o simili, tutto lavoro che quindi deve fare l'arduino, e li tu non lo fai
In particolare non "strippa" il codice 0x55 che sarebbe l'inizio della trasmissione, e in nessuno dei tuoi "elenchi di cose ricevute" si vede. Se non lo vedi è perchè non lo ricevi, e se non lo ricevi è perchè hai problemi a livello di comunicazione lato LIN bus
e qui ho visto un paio di cose: di default il LIN bus sembra andare a 9600bps, non 19200, ti conviene provare un po' di velocità, con costanza apri la seriale a 19200, poi a 9600, poi a 4800, e via così
poi la parità che usi (8E1) non è lo standard LIN, viene usata da BMW, ma non in un LIN bus, in una sua cosa propietaria
da una ricerca è saltato fuori che varie persone sono riuscite a leggere il LINbus con una UNO e la sua software serial, quindi nemmeno c'è la possibilità di cambiare parità, ergo usa la parità di default
inoltre io sono sempre convinto che la trasmissione LIN è composta da massimo 11 byte preceduti da un "silenzio" lungo almeno 13 bit
1 byte 0x55 Start e sincronismo tra i device
1 byte di indirizzo, dove alcuni bit specificano l'indirizzo, e altri sono di parità aggiuntiva
1, 2, 4 oppure 8 (ma non 3 o 5 o 6 o 7) byte di "risposta" (viene chiamata risposta anche quando viene trasmessa dal master)
1 byte di CRC o checksum o quello che è
ora, 1 + 2 + al massimo 8 fa al massimo 11
dagli esempi che ho trovato sono sicuro che la lunghezza di messaggi "omologhi" (che vuol dire che fanno cose simili) è costante, dipende dal tipo di messaggio, ma non esiste che per regolare una ventola un messaggio sia lungo 7 mentre per regolare l'altra il messaggio sia lungo 45, anche perchè è evidente che le ventole sono "simili" come progetto, quindi non è che in sede di installazione l'operaio che le monta debba scoprire la lunghezza del messaggio
da ultimo tieni presente che il protocollo LINbus prevede delle tolleranze sulle velocità, e siccome i device slave "non" hanno un oscillatore a cristallo, ma si regolano in base alla cadenza dello 0x55 iniziale non è escluso che le tolleranze dell'oscillatore di arduino non vadano bene , potrebbe essere necessario, per migliorare la qualità della trasmissione, di "aggiustare" di qualche percento i bps della seriale
Comunque, ripeto, fino a che non vedi gli 0x55 NON stai ricevendo correttamente dal lato LINbus
da ultimo lo schema: spero tu ti sia sbagliato e non sia quello lo schema che usi, dato che ti sei dimenticato di mettere il regolatore di tensione citato nella documentazione del trasnceiver
quindi vedi di mettere un regolatore a 3v3 e usare quello per connetttere la resistenza di Pull-up
Inoltre il piedino di fault lo metti in una define, ma non ne fai la pinmode e non lo usi, credo debba essere alto
E adesso lasiamelo dire: metà di queste cose te le avevo già dette, l'altra meta viene da una veloce scorsa al datasheet del 2004, che potevi fare anche tu

Grazie Nelson, porta pazienza ma sono un perito meccanico.
Ora cerco di capire quello che hai scritto e metterlo in pratica.

Tranquillo, io son perito elettrotecnico
basta non essere ingannieri................

Buona sera,
ho corretto gli errori che avevo fatto nel circuito, così mi sembra vada bene, lo potete vedere nell'allegato.
Ho provato a leggere la LIN con il codice sotto ma legge per 2-3 sec poi non riceve più niente. Nei pochi secondi che legge qualche 0x55 c'è.

#define PIN_TXE 18
#define PIN_CS 2
#define PIN_FAULT 9
uint8_t rxByte[8];

void setup() {
  pinMode(PIN_TXE, OUTPUT);
  pinMode(PIN_CS, OUTPUT);
  pinMode(PIN_FAULT, OUTPUT);
  digitalWrite(PIN_TXE, LOW);
  digitalWrite(PIN_CS, HIGH);
  digitalWrite(PIN_FAULT, HIGH);
  Serial1.begin(9600);
  Serial.begin(19200); 
  Serial.println("Due debug Comms");

  delay(100);
}

void loop() {
  byte actuallyRead = Serial1.readBytes(rxByte, 16);
  if (actuallyRead > 0)
  {
    for (uint32_t i = 0; i < actuallyRead; i++)
    {
      Serial.println(rxByte[i], HEX);
    }
  }
}

Schema.png

Per prima cosa io non ti ho indicato come modificare il circuito, ti ho detto che non era quello appropriato, non associarmi con azioni che non condivido...
Poi, non capisco perché dopo aver modificato il circuito hai anche sentito l'esigenza di scrivere un programma nuovo e sbagliato
Adesso sono in ferie, e poco posso fare
Ma se analizzi per bene il tuo programma un qualche problema lo trovi

Scusa Nelson, ho corretto la frase.
Ma c'è ancora qualcosa di sbagliato nel circuito?

Il programma non l'ho scritto adesso, è sempre lo stesso che uso per leggere i messaggi che girano sulla LIN.
Con questo programma leggo le stringhe, faccio l'analisi per capire quali sono i comandi che poi riporto nell'alto programma che comanda le ventole.

E' qui l'errore:"uint8_t rxByte[8];"?

Ciao a tutti,
ho sistemato la schedina che aveva una saldatura difettosa, ho eliminato alcune cose che sul datasheet del MCP2004 davano come opzionali, in allegato lo schema.
Ho corretto l'errore nel codice (spero) e messo la parità std .
Il pin Fault l'ho messo LOW per disabilitare la TX che non mi serve (da datasheet MCP2004).
Ora riesco a leggere la LIN con continuità.
Ho fatto varie prove a 4800, 9600, 19200 ma il byte 0x55 c'è solo a 9600 quindi considero 9600 la velocità corretta.
Le stringhe che leggo con tutto spento sono così:

55 B1 0 40 0 0 38 38 0 84 CA 0
55 39 40 0 40 0 10 10 0 0 5F 0
55 78 0 0 80 0 0 0 0 0 7F 0
55 B4 0 3 0 0 0 0 0 0 FC 0

0x55 da il sincronismo tra i device
0xB1, 0x39, 0x78, 0xB4 sono gli indirizzi
poi ci sono 8 byte di dati
0xCA, 0X5F, 0X7F, 0xFC sarà il CRC o checksum o quello che è
0x0 chiude la stringa

Dopo una prima fase (circa 20sec) dove le stringhe sono perfettamente regolari inizia a perdere pezzi e alterna righe di 12 byte con righe da 11 e 10 e alcune stringhe diventano invece molto lunghe.
Quando si perde qualche pezzo perde anche il byte di checksum

Suggerimenti?

Grazie
Mauro

/Arduino Due Board, Programming Port, LIN Test
//Attempt to interface with MCP2004-e/p LIN Transceiver
//Due project, Receive

#define PIN_CS 2
#define PIN_FAULT 9
uint8_t rxByte[11];

void setup() {
  pinMode(PIN_CS, OUTPUT);
  pinMode(PIN_FAULT, OUTPUT);
  digitalWrite(PIN_CS, HIGH);
  digitalWrite(PIN_FAULT, LOW);
  Serial2.begin(9600);
  Serial.begin(19200);
  Serial.println("Due debug Comms");

  delay(100);
}

void loop() {
  byte actuallyRead = Serial2.readBytes(rxByte, 11); //Read UP TO 11 bytes
  if (actuallyRead > 0)
  {
    for (uint8_t i = 0; i < actuallyRead; i++)
    {
      Serial.println(rxByte[i], HEX);
    }
  }
}

Schema.png

Tu dimensioni una rxbyte di 8 elementi, ma dopo fai una readbytes dove ne fai leggere 16, sbordando e andando a scrivere in aree di memoria dove non devi
Stesso errore che avevi fatto con lo array di lunghezze...
Consiglio: tratta la ricezione per singolo byte ricevuto

E aggiungo:
Non è che non voglio metterti il programma
È che sono in ferie e ho solo tablet e furbofono
Un po' poco per scrivere programmi

Grazie Nelson,
i tuoi consigli mi sono utilissimi e poi mi piace dovermi sbattere un pò per trovare la soluzione.

Ciao a tutti,
dopo avere sistemato il codice di lettura ho letto la LIN in modo penso corretto.
Leggo stringhe con la stessa lunghezza di 12 byte,
cominciano con 0x55,
ho 4 indirizzi ma le stringhe che interessano a me hanno indirizzo 0x78,
il 4° byte della stringa contiene l'indicazione di cosa devono fare le ventole e il riscaldamento

alcune stringhe di esempio:

55 B1 0 0 11 0 38 38 0 84 F9 0
55 39 40 0 40 0 10 10 0 0 5F 0
55 78 0 7 80 0 0 0 0 0 78 0 <---------
55 B4 0 3 0 0 0 0 0 0 FC 0

Ho modificato il codice per leggere la LIN e comandare le ventole ma non riesco a farlo funzionare.
La compilazione non da errori ma quando accendo il quadro le ventole partono al massimo e non fanno altro.
Se stampo la variabile "trovato" mi da sempre 0.
Ho fatto 1000 modifiche ma non ne esco. Ho bisogno di un esperto.
Di seguito il codice:

[code]
// CODICE RILEVAZIONE EVENTI SU LINBUS LEXUS e COMANDO VENTOLE PWM
// di Nelson "StandardOil"

#include <DuePWM.h>
#define PIN_CS 2
#define PIN_FAULT 9
#define PWM_FREQ1  20000
#define PWM_FREQ2  20000
uint32_t pwm_duty = 255; // 255 = 0% duty cycle
DuePWM pwm( PWM_FREQ1, PWM_FREQ2 );
byte comandi[16][4];// 16 comandi per 4 byte massimi
byte lunghez[1]; // 1 lunghezze

void setup(void)
{
  pinMode(PIN_CS, OUTPUT);
  pinMode(PIN_FAULT, OUTPUT);
  //digitalWrite(PIN_TXE, HIGH);
  digitalWrite(PIN_CS, HIGH);
  digitalWrite(PIN_FAULT, LOW);
  Serial2.begin(9600); //LIN Serial Rx
  Serial.begin(9600);
  pwm.setFreq1( PWM_FREQ1 );
  pwm.setFreq2( PWM_FREQ2 );
  pwm.pinFreq1( 6 );  // Pin 6 Vent SX freq set to "pwm_freq1" on clock A
  pwm.pinFreq2( 7 );  // Pin 7 Vent DX freq set to "pwm_freq2" on clock B
}
void loop(void)
{
  void Switch_Case_Comando_Ventole ();
}
byte parserizza(byte in)
{
  // riceve byte a byte un comando e lo usa per riconoscere il comando complessivo
  // dichiaro una matrice di matrici di byte
  // il problema è che le sequenza non hanno lunghezza uguale tra loro
  // quindi devo anche dichiarare un array di lunghezze
  // potessi usare le stringhe, sarebbe comodo ma esistono degli 00 nel flusso
  // quindi una matrice bidimensionale di byte (larga quanto il più lungo comando)
  // con una matrice monodimensionale di lunghezze

  // inizializzo

  //TUTTO SPENTO
  comandi[1][1] = 0x55;
  comandi[1][2] = 0x78;
  comandi[1][3] = 0x0;
  comandi[1][4] = 0x0;
  lunghez[1] = 4;

  //VENTOLA SX_3 DX_0
  comandi[2][1] = 0x55;
  comandi[2][2] = 0x78;
  comandi[2][3] = 0x0;
  comandi[2][4] = 0xB;
  lunghez[2] = 4;

  //VENTOLA SX_0 DX_3
  comandi[3][1] = 0x55;
  comandi[3][2] = 0x78;
  comandi[3][3] = 0x0;
  comandi[3][4] = 0xB0;
  lunghez[3] = 4;

  //VENTOLA SX_3 DX_3
  comandi[4][1] = 0x55;
  comandi[4][2] = 0x78;
  comandi[4][3] = 0x0;
  comandi[4][4] = 0xBB;
  lunghez[4] = 4;

  //VENTOLA SX_2 DX_3
  comandi[5][1] = 0x55;
  comandi[5][2] = 0x78;
  comandi[5][3] = 0x0;
  comandi[5][4] = 0xBA;
  lunghez[5] = 4;

  //VENTOLA SX_3 DX_2
  comandi[6][1] = 0x55;
  comandi[6][2] = 0x78;
  comandi[6][3] = 0x0;
  comandi[6][4] = 0xAB;
  lunghez[6] = 4;

  //VENTOLA SX_2 DX_0
  comandi[7][1] = 0x55;
  comandi[7][2] = 0x78;
  comandi[7][3] = 0x0;
  comandi[7][4] = 0xA;
  lunghez[7] = 4;

  //VENTOLA SX_0 DX_2
  comandi[8][1] = 0x55;
  comandi[8][2] = 0x78;
  comandi[8][3] = 0x0;
  comandi[8][4] = 0xA0;
  lunghez[8] = 4;

  //VENTOLA SX_2 DX_2
  comandi[9][1] = 0x55;
  comandi[9][2] = 0x78;
  comandi[9][3] = 0x0;
  comandi[9][4] = 0xAA;
  lunghez[9] = 4;

  //VENTOLA SX_1 DX_2
  comandi[10][1] = 0x55;
  comandi[10][2] = 0x78;
  comandi[10][3] = 0x0;
  comandi[10][4] = 0xA9;
  lunghez[10] = 4;

  //VENTOLA SX_2 DX_1
  comandi[11][1] = 0x55;
  comandi[11][2] = 0x78;
  comandi[11][3] = 0x0;
  comandi[11][4] = 0x9A;
  lunghez[11] = 4;

  //VENTOLA SX_1 DX_1
  comandi[12][1] = 0x55;
  comandi[12][2] = 0x78;
  comandi[12][3] = 0x0;
  comandi[12][4] = 0x99;
  lunghez[12] = 4;

  //VENTOLA SX_0 DX_1
  comandi[13][1] = 0x55;
  comandi[13][2] = 0x78;
  comandi[13][3] = 0x0;
  comandi[13][4] = 0x90;
  lunghez[13] = 4;

  //VENTOLA SX_1 DX_0
  comandi[14][1] = 0x55;
  comandi[14][2] = 0x78;
  comandi[14][3] = 0x0;
  comandi[14][4] = 0x9;
  lunghez[14] = 4;

  //VENTOLA SX_3 DX_1
  comandi[15][1] = 0x55;
  comandi[15][2] = 0x78;
  comandi[15][3] = 0x0;
  comandi[15][4] = 0x9B;
  lunghez[15] = 4;

  //VENTOLA SX_1 DX_3
  comandi[16][1] = 0x55;
  comandi[16][2] = 0x78;
  comandi[16][3] = 0x0;
  comandi[16][4] = 0xB9;
  lunghez[16] = 4;

  //siccome leggo il comando byte a byte devo tenere traccia di quanto lungo ho letto
  //e siccome devo confrontarlo con 4 possibili comandi devo avere 4 indici, uno per possibile comando
  // statico per non perdere l'informazione da un ingresso al successivo
  static byte trovato[4] = { 0x0, 0x0, 0x0, 0x0}; // variabili locali vanno inizializzate
  // adesso conosco un byte e vedo se corrisponde con la posizione raggiunta in ognuno dei possibili comandi
  for (byte i = 0; i < 4; i++)
  {
    // per ogni comando
    if (comandi[i][trovato[i]] != in)
    {
      // se il byte 'in' non corrisponde al byte in posizione [trovato[i]]
      // non e' il carattere giusto
      trovato[i] = 0; // riporto indietro il contatore
    }
    else
    {
      Serial.println(trovato[1], HEX);
      if (trovato[i] == lunghez[i]) // è il carattere giusto o siamo alla fine del comando oppure no
      {
        trovato[i] = 0; // ho trovato tutti i byte riporto a zero l'indice
        return i + 1; // me ne esco da questa funzione restituendo il numero del comando trovato più uno perchè zero indica comando non trovato
      }
      else
      {
        // comando non ancora finito, devo aspettare altri byte per sepere se è il giusto
        // aggiorno l'indice per controllare il prossimo byte
        trovato[i]++;
      }
    }
  }
  return 0; //restituisco 0 -> comando non trovato
}

Questo la seconda parte di codice:

void Switch_Case_Comando_Ventole()
{ byte comando = 0;
  if (Serial2.available())
  {
    // un byte disponibile -  passo a trattarlo
    comando = parserizza((byte)Serial2.read());
    // tutto il lavoro lo fa la parserizza che restituisce un valore numerico
    // 0 per non trovato
    // 1 per trovato primo comando
    // 2 per trovato.......
  }
  switch (comando)
  {
    case 0: //comando non trovato non fa niente

      break;

    case 1: //TUTTO SPENTO
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 2:  //VENTOLA SX_3 DX_0
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 3:  //VENTOLA SX_0 DX_3
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    case 4: //VENTOLA SX_3 DX_3
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    case 5:  //VENTOLA SX_2 DX_3
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    case 6:  //VENTOLA SX_3 DX_2
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 7: //VENTOLA SX_2 DX_0
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 8: //VENTOLA SX_0 DX_2
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 9:  //VENTOLA SX_2 DX_2
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 10:  //VENTOLA SX_1 DX_2
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 11:  //VENTOLA SX_2 DX_1
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 12: //VENTOLA SX_1 DX_1
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 13:  //VENTOLA SX_0 DX_1
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 14: //VENTOLA SX_1 DX_0
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 15:  //VENTOLA SX_3 DX_1
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 16:  //VENTOLA SX_1 DX_3
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    default:

      break;
  }
}

Buonasera,
dato che ora che leggo nel modo corretto la LIN la stringa che devo leggere è molto più semplice ho provato a riscrivere il codice.
Non mi da errori di compilazione ma le ventole non girano o meglio si mettono a girare quando vogliono solo al massimo della velocità.
Ho bisogno del vostro aiuto:

// CODICE RILEVAZIONE EVENTI SU LINBUS LEXUS e COMANDO VENTOLE PWM

#include <DuePWM.h>
#define PIN_CS 2
#define PIN_FAULT 9
#define PWM_FREQ1  20000
#define PWM_FREQ2  20000
uint32_t pwm_duty = 255; // 255 = 0% duty cycle
DuePWM pwm( PWM_FREQ1, PWM_FREQ2 );
byte comando;
byte last_comando;
static byte trovato[3] = { 0, 0, 0 };
byte actuallyRead;
unsigned long lastRx;

void setup(void)
{
  pinMode(PIN_CS, OUTPUT);
  pinMode(PIN_FAULT, OUTPUT);
  digitalWrite(PIN_CS, HIGH);
  digitalWrite(PIN_FAULT, LOW);
  Serial.begin(9600); //debug serial
  Serial.println("Due debug Comms");
  Serial2.begin(9600); //LIN Serial Rx
  pwm.setFreq1( PWM_FREQ1 );
  pwm.setFreq2( PWM_FREQ2 );
  pwm.pinFreq1( 6 );  // Pin 6 Vent SX freq set to "pwm_freq1" on clock A
  pwm.pinFreq2( 7 );  // Pin 7 Vent DX freq set to "pwm_freq2" on clock B
  comando = 0x0;
  last_comando = 0x0;
}
void loop(void)
{
label:
  if ((millis() - lastRx) > 500)
  {
    if (Serial2.available())
    {
      actuallyRead = Serial2.read();
      lastRx = millis();
      //Serial.println(actuallyRead, HEX); //qui leggo correttamente la LIN
      if (actuallyRead == 0x55)
      {
        trovato[1] = 0x55;
        actuallyRead = Serial2.read();
        lastRx = millis();
        if (actuallyRead == 0x78)
        {
          trovato[2] = 0x78;
          actuallyRead = Serial2.read();
          lastRx = millis();
          if (actuallyRead == 0x0)
          {
            trovato[3] = 0x0;
            byte comando = Serial2.read();
            lastRx = millis();
            if ( comando != last_comando)
            {
              void Switch_Case_Comando ();
            }
            else
            {
              goto label;
            }
          }
          else
          {
            goto label;
          }
        }
        else
        {
          goto label;
        }
      }
      else
      {
        goto label;
      }
    }
    else
    {
      goto label;
    }
  }
}

Il secondo pezzo:

void Switch_Case_Comando ()
{
  switch (comando)
  {
    case 0x0 : //TUTTO SPENTO
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 0xB :  //VENTOLA SX_3 DX_0
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 0xB0:  //VENTOLA SX_0 DX_3
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    case 0xBB: //VENTOLA SX_3 DX_3
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    case 0xBA:  //VENTOLA SX_2 DX_3
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    case 0xAB:  //VENTOLA SX_3 DX_2
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 0xA: //VENTOLA SX_2 DX_0
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 0xA0: //VENTOLA SX_0 DX_2
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 0xAA:  //VENTOLA SX_2 DX_2
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 0xA9:  //VENTOLA SX_1 DX_2
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 50% duty cycle on Pin 7
      break;

    case 0x9A:  //VENTOLA SX_2 DX_1
      pwm_duty = 130; // 50% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 50% duty cycle on Pin 6
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 0x99: //VENTOLA SX_1 DX_1
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 0x90:  //VENTOLA SX_0 DX_1
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 0% duty cycle on Pin 6
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 0x9: //VENTOLA SX_1 DX_0
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm_duty = 255; // 0% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 0% duty cycle on Pin 7
      break;

    case 0x9B:  //VENTOLA SX_3 DX_1
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 75% duty cycle on Pin 6
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 25% duty cycle on Pin 7
      break;

    case 0xB9:  //VENTOLA SX_1 DX_3
      pwm_duty = 200; // 25% duty cycle
      pwm.pinDuty( 6, pwm_duty );  // 25% duty cycle on Pin 6
      pwm_duty = 70; // 75% duty cycle
      pwm.pinDuty( 7, pwm_duty );  // 75% duty cycle on Pin 7
      break;

    default:

      break;
  }
}

Buongiorno a tutti,

se io scrivo:

  if (Serial2.available())
  {
    inByte = Serial2.read ();

    if (inByte == 0x55)
    {
      i = 0;
      messaggio [0] = inByte;
      inByte = Serial2.read ();
      for (i = 0; i < 12; i++)
        messaggio [i] = inByte ;
      Serial.println ( messaggio [i], HEX);
      if (messaggio[0] == 0x55 && messaggio[1] == 0x78 && messaggio[2] == 0x0 )
      {
        comando = messaggio[3];

nell'array messaggio 0 avrò il byte 0x55 e a seguire quelli che legge successivamente?

Buongiorno a tutti,
il progetto è concluso e funziona perfettamente.
Pubblico il codice definitivo per chi è interessato:

// CODICE RILEVAZIONE EVENTI SU LINBUS LEXUS e COMANDO VENTOLE PWM

#define PIN_CS 2
#define PIN_FAULT 9
#define V_SX 6
#define V_DX 7

int V0 = 255;
int V1 = 170;
int V2 = 85;
int V3 = 0;

byte stato = 0;
byte comando;

void setup()
{
  pinMode(PIN_CS, OUTPUT);
  pinMode(PIN_FAULT, OUTPUT);
  pinMode(V_SX, OUTPUT);
  pinMode(V_DX, OUTPUT);
  digitalWrite(PIN_FAULT, HIGH);
  analogWrite( V_SX , V0 ); //VENTOLA Sx FERMA
  analogWrite( V_DX , V0 ); //VENTOLA Dx FERMA
  //Serial.begin(57600); //debug serial
  //Serial.println("Due debug Comms");
  Serial3.begin(9600); //LIN Serial Rx
  digitalWrite(PIN_CS, HIGH);
}

void loop()

{
  while (Serial3.available())
  {
    byte rx = Serial3.read();
    //Serial.println (rx , HEX);
    switch (stato)
    {
      case 0:
        if (rx == 0x55)      stato = 1;
        else                 stato = 0;
        break;
      case 1:
        if (rx == 0x78)      stato = 2;
        else if (rx == 0x55) stato = 1;
        else                 stato = 0;
        break;
      case 2:
        if (rx == 0x00)      stato = 3;
        else if (rx == 0x55) stato = 1;
        else                 stato = 0;
        break;
      case 3:
        if (rx == 0x55)      stato = 1;
        else {
          switch (rx)
          {
            case 0x0 : // 0x0 TUTTO SPENTO
              analogWrite( 6, V0 );
              analogWrite( 7, V0 );
              break;

            case 0xB :  // 0xB VENTOLA SX_3 DX_0
              analogWrite( 6, V3 );
              analogWrite( 7, V0 );
              break;

            case 0x7B :  // 0x7B VENTOLA SX_3 DX_0 RISC Dx_3
              analogWrite( 6, V3 );
              analogWrite( 7, V0 );
              break;

            case 0x6B :  // 0x6B VENTOLA SX_3 DX_0 RISC Dx_2
              analogWrite( 6, V3 );
              analogWrite( 7, V0 );
              break;

            case 0x5B :  // 0x5B VENTOLA SX_3 DX_0 RISC Dx_1
              analogWrite( 6, V3 );
              analogWrite( 7, V0 );
              break;

            case 0xB0 :  // 0xB0 VENTOLA SX_0 DX_3
              analogWrite( 6, V0 );
              analogWrite( 7, V3 );
              break;

            case 0xB7 :  // 0xB7 VENTOLA SX_0 DX_3 RISC Sx_3
              analogWrite( 6, V0 );
              analogWrite( 7, V3 );
              break;

            case 0xB6 :  // 0xB6 VENTOLA SX_0 DX_3  RISC Sx_2
              analogWrite( 6, V0 );
              analogWrite( 7, V3 );
              break;

            case 0xB5 :  // 0xB5 VENTOLA SX_0 DX_3 RISC Sx_1
              analogWrite( 6, V0 );
              analogWrite( 7, V3 );
              break;

            case 0xBB : // 0xBB VENTOLA SX_3 DX_3
              analogWrite( 6, V3 );
              analogWrite( 7, V3 );
              break;

            case 0xBA :  // 0xBA VENTOLA SX_2 DX_3
              analogWrite( 6, V2 );
              analogWrite( 7, V3 );
              break;

            case 0xAB :  // 0xAB VENTOLA SX_3 DX_2
              analogWrite( 6, V3 );
              analogWrite( 7, V2 );
              break;

            case 0xA : // 0xA VENTOLA SX_2 DX_0
              analogWrite( 6, V2 );
              analogWrite( 7, V0 );
              break;

            case 0x7A :  // 0x7A VENTOLA SX_2 DX_0 RISC Dx_3
              analogWrite( 6, V2 );
              analogWrite( 7, V0 );
              break;

            case 0x6A :  // 0x6A VENTOLA SX_2 DX_0 RISC Dx_2
              analogWrite( 6, V2 );
              analogWrite( 7, V0 );
              break;

            case 0x5A :  // 0x5A VENTOLA SX_2 DX_0 RISC Dx_1
              analogWrite( 6, V2 );
              analogWrite( 7, V0 );
              break;

            case 0xA0 : // 0xA0 VENTOLA SX_0 DX_2
              analogWrite( 6, V0 );
              analogWrite( 7, V2 );
              break;

            case 0xA7 : // 0xA7 VENTOLA SX_0 DX_2 RISC Sx_3
              analogWrite( 6, V0 );
              analogWrite( 7, V2 );
              break;

            case 0xA6 : // 0xA6 VENTOLA SX_0 DX_2 RISC Sx_2
              analogWrite( 6, V0 );
              analogWrite( 7, V2 );
              break;

            case 0xA5 : // 0xA5 VENTOLA SX_0 DX_2 RISC Sx_1
              analogWrite( 6, V0 );
              analogWrite( 7, V2 );
              break;

            case 0xAA :  // 0xAA VENTOLA SX_2 DX_2
              analogWrite( 6, V2 );
              analogWrite( 7, V2 );
              break;

            case 0xA9 :  // 0xA9 VENTOLA SX_1 DX_2
              analogWrite( 6, V1 );
              analogWrite( 7, V2 );
              break;

            case 0x9A :  // 0x9A VENTOLA SX_2 DX_1
              analogWrite( 6, V2 );
              analogWrite( 7, V1 );
              break;

            case 0x99 : // 0x99 VENTOLA SX_1 DX_1
              analogWrite( 6, V1 );
              analogWrite( 7, V1 );
              break;

            case 0x90 :  // 0x90 VENTOLA SX_0 DX_1
              analogWrite( 6, V0 );
              analogWrite( 7, V1 );
              break;

            case 0x9 : // 0x9 VENTOLA SX_1 DX_0
              analogWrite( 6, V1 );
              analogWrite( 7, V0 );
              break;

            case 0x79 :  // 0x79 VENTOLA SX_1 DX_0 RISC Dx_3
              analogWrite( 6, V1 );
              analogWrite( 7, V0 );
              break;

            case 0x69 :  // 0x69 VENTOLA SX_1 DX_0 RISC Dx_2
              analogWrite( 6, V1 );
              analogWrite( 7, V0 );
              break;

            case 0x59 :  // 0x59 VENTOLA SX_1 DX_0 RISC Dx_1
              analogWrite( 6, V1 );
              analogWrite( 7, V0 );
              break;

            case 0x9B :  // 0x9B VENTOLA SX_3 DX_1
              analogWrite( 6, V3 );
              analogWrite( 7, V1 );
              break;

            case 0xB9 :  // 0xB9 VENTOLA SX_1 DX_3
              analogWrite( 6, V1 );
              analogWrite( 7, V3 );
              break;

            case 0x7 :  // 0x7 VENTOLA SX_0 DX_0 RISC SX_3 DX_0
              analogWrite( 6, V0 );
              analogWrite( 7, V0 );
              break;

            case 0x6 :  // 0x6 VENTOLA SX_0 DX_0 RISC SX_2 DX_0
              analogWrite( 6, V0 );
              analogWrite( 7, V0 );
              break;

            case 0x5 :  // 0x5 VENTOLA SX_0 DX_0 RISC SX_1 DX_0
              analogWrite( 6, V0 );
              analogWrite( 7, V0 );
              break;

            case 0x97 :  // 0x97 VENTOLA SX_0 DX_1
              analogWrite( 6, V0 );
              analogWrite( 7, V1 );
              break;

            case 0x70 :  // 0x70 VENTOLA SX_0 DX_0  RISC SX_0 DX_3
              analogWrite( 6, V0 );
              analogWrite( 7, V0 );
              break;

            case 0x60 :  // 0x60 VENTOLA SX_0 DX_0  RISC SX_0 DX_2
              analogWrite( 6, V0 );
              analogWrite( 7, V0 );
              break;

            case 0x50 :  // 0x50 VENTOLA SX_0 DX_0  RISC SX_0 DX_1
              analogWrite( 6, V0 );
              analogWrite( 7, V0 );
              break;

            default:
              break;
          }
          stato = 0;
        }
    }
  }
}