Nel camper di mio padre c’è un MPPT CBE PRM350 e relativo pannello CBE PT742 che indica (o meglio, dovrebbe indicare) quanto attualmente producono i pannelli.
Purtroppo a volte segna 0 A anche a produzione attiva (e le batterie si stanno ricaricando – se fossero cariche dovrebbe giustamente segnare 0 A).
Ho deciso di studiare come funziona, non so se riuscirò a ripararlo o meno, ma intanto riporto qui i risultati, magari serviranno a qualcuno.

Il tutto è basato su un Microchip Technology AVR128DA32 alimentato a 3.3V.
Si capisce subito che del connettore a 8 pin vengono usati solo i 4 centrali. Testando con il multimetro si trovano i primi due: GND e +12V. Il voltaggio che mostra il display è campionato proprio dai +12V.
Per l’amperaggio mostrato però ci sarà una certa forma di comunicazione tra MPPT e pannello, tramite i rimanenti due pin.
Ma quale protocollo di comunicazione? Mi collego ai due pin, e su uno dei due, quello che battezzerò “RX”, osservo questo:

Sembra una comunicazione seriale. Un bit singolo dura circa 440us, ed è un valore che ritorna molte volte ad es, il primo low è di 880us.
In un secondo “ci stanno” 1/0,000440 s = 2270 baud, che si avvicina molto al valore standard di 2400 baud.
Provo a collegare il mio logic analyzer cinese e con PulseView e decoder seriale 8N1 2400 ricevo dei pacchetti che “hanno un senso”: c’è sempre uno start byte AA e i valori cambiano con il variare degli ampere.
AA 00 55 FF
AA 00 54 FE
AA 01 53 FE
AA 01 58 03
Il primo è sempre AA
ll secondo cambia in base alla grandezza visualizzata: è la parte “grossa” del valore. Ogni unità vale 100 decimi di ampere.
Il terzo è la parte “fine” del valore: decimi di ampere da 0 a 99.
L’ultima (e qui mi sono fatto aiutare da ChatGPT, lo ammetto), è il checksum calcolato così:
checksum = (1 Byte + 2 Byte + 3 Byte) & 0xFF
Quindi negli esempi catturati abbiamo:
AA 00 55 FF → 0×100 + 85 = 85 → 8,5 A
AA 00 54 FE → 0×100 + 84 = 84 → 8,4 A
AA 01 53 FE → 1×100 + 83 = 183 → 18,3 A
AA 01 58 03 → 1×100 + 88 = 188 → 18,8 A
Ma quindi cosa va storto?
Esattamente non lo so, dato che durante il test funzionava, ma VMax 2,38 V e VPP 1,77 V sul pin RX mi sembrano decisamente bassi per logica a 3,3 V.
Lo stage RX sul pannellino sembra essere resistenza serie 1,5 k , zener 3.3 , pin PC1 del AVR128DA32.
Secondo me il cavo di comunicazione è troppo lungo o ci sono resistenze di pull up mancanti/troppo alte.
Per ora mi fermo qui, perché sto valutando il cambio batterie con nuove al litio, e questo mi porta verso la sostituzione del CBE PRM350 con qualcosa di piu’ serio, tipo Victron MPPT 100/30.
Vi lascio con uno sketch Arduino di prova (in realtà ESP8266 dato che gira nativamente a 3.3v) e video di “vittoria” riguardo la decodifica del protocollo.
Una potenziale applicazione potrebbe essere: decodificare protocollo Victron VE.Direct e creare un “traduttore” per mantenere lo stesso pannello che è già montato nel mobile del camper.

// =============================================================
// Simulatore protocollo seriale CBE MPPT350 → PT742
// WEMOS D1 Mini / ESP8266
// =============================================================
#include <SoftwareSerial.h>
// -------------------------------------------------------------
// PIN CONFIG
// -------------------------------------------------------------
// TX verso PT742
// D2 = GPIO4
#define PIN_TX D2
SoftwareSerial cbeSerial(-1, PIN_TX); // RX non usato -> -1
// -------------------------------------------------------------
// PARAMETRI SIMULAZIONE
// -------------------------------------------------------------
int corrente_dA = 83; // corrente Decimi Ampere inviata
int corrente_max_dA = 200; // max 20.0A
int corrente_min_dA = 50; // min 5.0A
// Intervallo invio
int intervallo_ms = 100;
// Direzione rampa
int direzione = 1;
// -------------------------------------------------------------
void setup() {
// Debug USB
Serial.begin(115200);
delay(500);
Serial.println();
Serial.println("Avvio simulatore CBE MPPT350");
cbeSerial.begin(2400);
delay(200);
}
void loop() {
invia_corrente(corrente_dA);
// Debug
Serial.print("Invio: ");
Serial.print(corrente_dA / 10.0, 1);
Serial.println(" A");
// Rampa
corrente_dA += direzione;
if (corrente_dA >= corrente_max_dA)
direzione = -1;
if (corrente_dA <= corrente_min_dA)
direzione = +1;
delay(intervallo_ms);
}
// -------------------------------------------------------------
// INVIO PACCHETTO
// -------------------------------------------------------------
void invia_corrente(int valore_dA) {
byte sync = 0xAA;
byte msb = (byte)(valore_dA / 100);
byte lsb = (byte)(valore_dA % 100);
byte checksum = (sync + msb + lsb) & 0xFF;
cbeSerial.write(sync);
cbeSerial.write(msb);
cbeSerial.write(lsb);
cbeSerial.write(checksum);
cbeSerial.flush();
}