Diy osd simple pour signal composite

bonjour a tous.
je cherche a faire un osd simple pour un projet robotique. je cherche simplement a rajouter de la data par dessus le signal video.
il y a bien longtemps je l'avais fais ave. un shield arduino uno.
c'était encombrant et pas adapté a mon besoin actuel.
y a t'il moyen de ce faire un osd au plus simple avec un esp32 par exemple ?
merci

Une piste ici

merci.
j'ai vu ces lien qui ramène vers un projet apparemment non abouti.
c'est maintenant un truc qui semble simple et intégré en natif dans presque toutes les carte de vol . meme les max7456 ne sembles plus trouvables :frowning:

Ce composant est obsolète.

Le projet n'est pas abouti mais il donne un principe de fonctionnement. Qui est détaillé ici

Le code pourrait être adapté pour travailler avec des synchros extraites d'une vidéo externe plutôt que de les générer dans le code.

c'est obsolète, mais ca bien ete remplacer par autre chose non !? :thinking:.
merci pour ton lien . ca a l'air vraiment intéressant. un esp32 semble en etre capable.
mais j'ai peur que ce soit pas dans mes compétences en l'état.

C'est-à-dire que le marché a un peu disparu.
Les vidéos sont maintenant complètement numériques.
Il semblerait qu'il y existe un clone chinois, AT7456. Je n'ai pas cherché.

alors j'ai trouver un firmware a installer via l'ide arduino a un minimosd .
techniquement ca fonctionne, mais je n'arrive pas encore a faire passer ce que je veu ... un peu comme si les baud rate était différent

alors j'ai trouvé un petit firmware, simple a lire . chargé avec un ftdi .
jusqu'à la aucun pb.

mais je ne metrise pas ce que fait l'osd . un peu comme si il ne reposé pas sur la même table ascii ...
est ce possible ?

On ne sait pas de quoi tu parles donc c'est difficile de t'aider.

tu as raison, c'est pas clair ... alors j'utilise une max 7456 minimosd.
avec ce firmware

`/*
  MinimOSD UART Text Firmware
  Corrigé avec mapping ASCII -> MAX7456
  UART: 9600 bauds
  Cible: MinimOSD / KV Team mod avec ATmega328P + MAX7456

  Commandes supportées :
    CLS
    TXT <col> <row> <texte>
    CLR <row>
    PING
    MODE PAL
    MODE NTSC
*/

#include <SPI.h>

static const uint8_t MAX7456_CS_PIN = 6;   // fréquent sur MinimOSD
static const uint32_t UART_BAUD = 9600;
static const bool DEFAULT_PAL = true;

// Registres MAX7456
static const uint8_t REG_VM0  = 0x00;
static const uint8_t REG_HOS  = 0x02;
static const uint8_t REG_VOS  = 0x03;
static const uint8_t REG_DMM  = 0x04;
static const uint8_t REG_DMAH = 0x05;
static const uint8_t REG_DMAL = 0x06;
static const uint8_t REG_DMDI = 0x07;
static const uint8_t REG_RB0  = 0x10;

// VM0
static const uint8_t VM0_ENABLE_OSD = 0x08;
static const uint8_t VM0_RESET      = 0x02;
static const uint8_t VM0_VIDEO_NTSC = 0x00;
static const uint8_t VM0_VIDEO_PAL  = 0x40;

// DMM
static const uint8_t DMM_CLEAR_DISPLAY = 0x04;
static const uint8_t DMM_AUTO_INC      = 0x01;

// Dimensions
static const uint8_t COLS = 30;
static const uint8_t ROWS_PAL = 16;
static const uint8_t ROWS_NTSC = 13;

bool isPal = DEFAULT_PAL;

static const uint8_t LINE_BUF_SIZE = 80;
char lineBuf[LINE_BUF_SIZE];
uint8_t lineLen = 0;

void maxWriteReg(uint8_t reg, uint8_t value) {
  digitalWrite(MAX7456_CS_PIN, LOW);
  SPI.transfer(reg);
  SPI.transfer(value);
  digitalWrite(MAX7456_CS_PIN, HIGH);
}

void maxSoftReset() {
  maxWriteReg(REG_VM0, VM0_RESET);
  delay(20);
}

void maxSetVideoMode(bool pal) {
  isPal = pal;

  maxSoftReset();

  for (uint8_t r = 0; r < 16; r++) {
    maxWriteReg(REG_RB0 + r, 0x02);
  }

  maxWriteReg(REG_HOS, 0x20);
  maxWriteReg(REG_VOS, 0x10);

  uint8_t vm0 = VM0_ENABLE_OSD | (pal ? VM0_VIDEO_PAL : VM0_VIDEO_NTSC);
  maxWriteReg(REG_VM0, vm0);

  delay(20);
}

void maxClearScreen() {
  maxWriteReg(REG_DMM, DMM_CLEAR_DISPLAY);
  delay(30);
}

void maxSetAddress(uint16_t addr) {
  maxWriteReg(REG_DMAH, (addr >> 8) & 0x01);
  maxWriteReg(REG_DMAL, addr & 0xFF);
}

// Mapping ASCII -> charset MAX7456
uint8_t mapAsciiToMax7456(char c) {
  // chiffres
  if (c >= '0' && c <= '9') return (uint8_t)c;

  // lettres majuscules
  if (c >= 'A' && c <= 'Z') return (uint8_t)c;

  // minuscules -> majuscules
  if (c >= 'a' && c <= 'z') return (uint8_t)(c - 32);

  switch (c) {
    case ' ': return 0x00;
    case '.': return 0x2E;
    case ':': return 0x3A;
    case '-': return 0x2D;
    case '=': return 0x3D;
    case '/': return 0x2F;
    case ',': return 0x2C;
    case '_': return 0x5F;
    case '(': return 0x28;
    case ')': return 0x29;
    default:  return 0x20;
  }
}

void maxPrintAt(uint8_t col, uint8_t row, const char *text) {
  if (col >= COLS) return;
  uint8_t maxRows = isPal ? ROWS_PAL : ROWS_NTSC;
  if (row >= maxRows) return;

  uint16_t addr = (uint16_t)row * COLS + col;
  maxSetAddress(addr);

  maxWriteReg(REG_DMM, DMM_AUTO_INC);

  digitalWrite(MAX7456_CS_PIN, LOW);
  SPI.transfer(REG_DMDI);

  while (*text && col < COLS) {
    SPI.transfer(mapAsciiToMax7456(*text++));
    col++;
  }

  SPI.transfer(0xFF);
  digitalWrite(MAX7456_CS_PIN, HIGH);
}

void maxClearLine(uint8_t row) {
  if (row >= (isPal ? ROWS_PAL : ROWS_NTSC)) return;

  char spaces[COLS + 1];
  for (uint8_t i = 0; i < COLS; i++) spaces[i] = ' ';
  spaces[COLS] = '\0';

  maxPrintAt(0, row, spaces);
}

void sendOk() {
  Serial.println(F("OK"));
}

void sendErr(const __FlashStringHelper *msg) {
  Serial.print(F("ERR "));
  Serial.println(msg);
}

void trimRight(char *s) {
  int n = strlen(s);
  while (n > 0 && (s[n - 1] == '\r' || s[n - 1] == '\n' || s[n - 1] == ' ' || s[n - 1] == '\t')) {
    s[n - 1] = '\0';
    n--;
  }
}

void skipSpaces(char *&p) {
  while (*p == ' ' || *p == '\t') p++;
}

bool parseUInt(char *&p, uint8_t &out) {
  skipSpaces(p);
  if (*p < '0' || *p > '9') return false;

  unsigned int val = 0;
  while (*p >= '0' && *p <= '9') {
    val = val * 10 + (*p - '0');
    p++;
  }

  if (val > 255) return false;
  out = (uint8_t)val;
  return true;
}

void handleCommand(char *cmd) {
  trimRight(cmd);

  if (strcmp(cmd, "CLS") == 0) {
    maxClearScreen();
    sendOk();
    return;
  }

  if (strcmp(cmd, "PING") == 0) {
    Serial.println(F("PONG"));
    return;
  }

  if (strcmp(cmd, "MODE PAL") == 0) {
    maxSetVideoMode(true);
    maxClearScreen();
    sendOk();
    return;
  }

  if (strcmp(cmd, "MODE NTSC") == 0) {
    maxSetVideoMode(false);
    maxClearScreen();
    sendOk();
    return;
  }

  if (strncmp(cmd, "TXT", 3) == 0) {
    char *p = cmd + 3;
    uint8_t col, row;

    if (!parseUInt(p, col)) {
      sendErr(F("bad col"));
      return;
    }
    if (!parseUInt(p, row)) {
      sendErr(F("bad row"));
      return;
    }

    skipSpaces(p);
    if (*p == '\0') {
      sendErr(F("missing text"));
      return;
    }

    maxPrintAt(col, row, p);
    sendOk();
    return;
  }

  if (strncmp(cmd, "CLR ", 4) == 0) {
    char *p = cmd + 4;
    uint8_t row;

    if (!parseUInt(p, row)) {
      sendErr(F("bad row"));
      return;
    }

    maxClearLine(row);
    sendOk();
    return;
  }

  sendErr(F("unknown cmd"));
}

void setup() {
  pinMode(MAX7456_CS_PIN, OUTPUT);
  digitalWrite(MAX7456_CS_PIN, HIGH);

  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);

  Serial.begin(UART_BAUD);
  delay(100);

  maxSetVideoMode(isPal);
  maxClearScreen();
  maxPrintAt(0, 0, "UART OSD READY");
  maxPrintAt(0, 1, isPal ? "MODE PAL" : "MODE NTSC");
}

void loop() {
  while (Serial.available()) {
    char c = (char)Serial.read();

    if (c == '\n' || c == '\r') {
      if (lineLen > 0) {
        lineBuf[lineLen] = '\0';
        handleCommand(lineBuf);
        lineLen = 0;
      }
    } else {
      if (lineLen < LINE_BUF_SIZE - 1) {
        lineBuf[lineLen++] = c;
      } else {
        lineLen = 0;
        sendErr(F("line too long"));
      }
    }
  }
}
`

derrière , j’utilise ce code


// Exemple de protocole texte simple vers le MinimOSD.
// À adapter au firmware exact du MinimOSD.
// Ici on suppose des commandes du genre :
// CLS
// TXT col row texte

#include<SoftwareSerial.h>
SoftwareSerial Serial2(6,5);//RX TX
//SoftwareSerial Serial3(6,5);
char test []= "41";

int distX_cm = 10;
int distY_cm = 5;

void osdClear() {
  Serial2.println("CLS");
}

void osdPrint(uint8_t col, uint8_t row, const String &text) {
  Serial2.print("TXT ");
  Serial2.print(col);
  Serial2.print(" ");
  Serial2.print(row);
  Serial2.print(" ");
  Serial2.println(text);
}

void setup() {
  Serial.begin(9600); 
  Serial2.begin(9600);   // MinimOSD

  delay(500);

  osdClear();
  osdPrint(3, 2, "X: ----");
  osdPrint(3, 4, "Y: ----");
}

void loop() {
  uint16_t tmp;


  static uint32_t lastDraw = 0;
  if (millis() - lastDraw >= 500) {
    lastDraw = millis();
    osdClear();

    String lineX = "X: ";
    
      lineX += String(distX_cm / 100.0f, 2);
 

    String lineY = "Y: ";
    
      lineY += String(distY_cm / 100.0f, 2);
      lineY += String(distY_cm);
   

    osdPrint(3, 2, lineX);   // haut gauche ligne 1
    osdPrint(3, 4, lineY);   // haut gauche ligne 2
  }
}


j’espère que c'est plus clair

il y a encore de ligne de code issu de différents essais .
mais le résultat sur l'ecran est erratique ....
par exemple

osdPrint(3, 4, "Y: ----");
juste modifier ce qui est entre guillemet m'invente des caractères bizarre, ce met a écrire a la suite du reste et donc ignorer col et row ...

La liaison entre ton code et le minimosd c'est une liaison filaire ou il y a une liaison sans fil?
Le minimosd retourne des messages d'erreur. Tu devrais les lire cela pourrait t'aider.

Modifier par quoi? Le minimosd gère un nombre limité de caractères.

alors je suis en filaire . il n'y a pas de message d'erreur ,

et par exemple
changer ca

osdPrint(3, 4, "Y: ----");

par ca

osdPrint(3, 4, "Y:");

suffi a mettre le boxon .

Tu ne peux pas le savoir ton code ne lit pas ce qui revient sur Serial2.
Il y a une bonne masse entre les éléments?

alors oui il y a une bonne masse.

c'est vrais que je ne lit pas serial2 mais a chaquz foix ca fait des modifications a l'écran. je me dit que le firmware accepte mes commande !?

Ton code semble bon. Donc, s'il y a un problème, soit c'est le firmware du minimosd, soit c'est dans la liaison entre les 2.

j'utilise softserial parce que sur nano. tu pense que ca peut venir de la ?

Je ne pense pas, mais le meiller moyen de le savoir serait faire un essai en utilisant Serial pour dialoguer avec ton minimosd.
Comme Serial sert aussi pour le téléchargement, il faut :

  • deconnecter Rx et Tx du minimosd, pour éviter un conflit sur ces broches et planter le téléchargement.
  • télécharger le code.
  • reconnecter Rx et Tx au minimosd.
  • brancher et voir ce qui se passe.

Je te suggererais aussi de faire varier la valeur que tu envoies. Pour voir si l'affichage se passe correctement. Faire dans loop un truc du genre:
distX_cm = (distX_cm + 1) % 11;
Tu devrais voir la valeur X changer de 0.00 à 0.10