Avamander / arduino-tvout

Arduino-TVout
325 stars 81 forks source link

do TVOut block or interfere with SPI communication? #144

Open ghost opened 1 year ago

ghost commented 1 year ago

Hello.

I have two arduino nano.

one is master, and one is slave.

master sends 2 int16_t variables and 1 double variable.

slave receives it successfully unless there are TVOut code.

if I add TVOut, the result data corrupted. (expected result : 1111,2222,3333.3, actual result : -18703, -0.00 like this)

is TVOut interfering the data?

Master Code :

void Video(int16_t torque_value, int16_t hook_value, double gyro_value)
{
  int8_t SPI_Buffer[50];
  static int spi_index_test = 0;
  static int spi_index = 0;

  SPI_Buffer[0] = *(int8_t *)(&gyro_value); 
  SPI_Buffer[1] = *((int8_t *)(&gyro_value)+1);
  SPI_Buffer[2] = *((int8_t *)(&gyro_value)+2);
  SPI_Buffer[3] = *((int8_t *)(&gyro_value)+3);
  SPI_Buffer[4] = *(int8_t *)(&hook_value);
  SPI_Buffer[5] = *((int8_t *)(&hook_value)+1);
  SPI_Buffer[6] = *(int8_t *)(&torque_value);
  SPI_Buffer[7] = *((int8_t *)(&torque_value)+1);

  if(!digitalRead(VIDEO_INT));
  {
    SPI.beginTransaction(setting_video); 
    #ifdef SS_VIDEO_D4
    PORTD &= ~B00010000; //PORTD : 0~7
    #endif

    spi_index_test = SPI.transfer(SPI_Buffer[spi_index]);
    if(spi_index_test >= 0)
    {
      spi_index = spi_index_test;
    }

    PORTD |= B00010000; //PORTD : 0~7
    SPI.endTransaction();
  }
}

Slave code :

#include <SPI.h>
#include <TVout.h>
#include <fontALL.h>

TVout TV;

#define LED_PIN_1 4
//#define RCV_READY_PIN_D5 5
#define RCV_READY_PIN_D3 3

#define DATA_LENGTH 7

volatile int8_t RCVD[20]; 
volatile byte pos = 0;; 
double rcv_data_1 = 0; 
int16_t rcv_data_2 = 0;
int16_t rcv_data_3 = 0;

unsigned long time_led_changed = 0;
boolean is_led_turned_on = false;

void setup() {
  TV.begin(NTSC,120,96);
  TV.set_vbi_hook(turnOnSPI); 
  TV.select_font(font4x6);
  TV.print(0,0, "ASCENDER DATA");

  pinMode(MISO, OUTPUT);
  pinMode(MOSI, INPUT);
  pinMode(SCK, INPUT);
  pinMode(SS, INPUT);
  pinMode(LED_PIN_1, OUTPUT);
  pinMode(RCV_READY_PIN_D3, OUTPUT);

  SPCR |= _BV(SPE); //SPI ENABLE
  SPCR &= ~_BV(MSTR); //MASTER/SLAVE SELECT
  SPCR |= _BV(SPIE); //SPI INTERRUPT ENABLE.

  SPI.setClockDivider(SPI_CLOCK_DIV16); 
  Serial.begin(9600);
}

void loop() {
  static unsigned long time_turned_on = 0;

  //rcv_data_1 = (double)((RCVD[3] << 24)|(RCVD[2] << 16)|(RCVD[1] << 8)|RCVD[0]);
  //rcv_data_2 = (RCVD[5]<<8)|(RCVD[4]);
  //rcv_data_3 = (RCVD[7]<<8)|(RCVD[6]);
  rcv_data_1 = *(double *)(RCVD);
  rcv_data_2 = *(int16_t *)(RCVD + 4);
  rcv_data_3 = *(int16_t *)(RCVD + 6);

  Serial.println(rcv_data_1);
  Serial.println(rcv_data_2);
  Serial.println(rcv_data_3);
  //Serial.println(pos);

  if(rcv_data_3 > 750)
  {
    //digitalWrite(LED_PIN_1, LOW); //LED_PIN : D4
    PORTD &= ~B00010000;
  }
  else if(rcv_data_3 <= 750 && rcv_data_3 >= -750)
  {
    //digitalWrite(LED_PIN_1, HIGH);
    PORTD |= B00010000;
  }
  else if(rcv_data_3 < -750)
  {
    //digitalWrite(LED_PIN_1, LOW);
    PORTD &= ~B00010000;
  }

    TV.print(0,8, "Torque : ");
    TV.print(36,8,"       ");
    TV.print(36,8,rcv_data_3); 
    TV.print(0,16,"HOOK : ");
    TV.print(32,16,"       ");
    TV.print(32,16,rcv_data_2);
    TV.print(0, 24, "GYRO : ");
    TV.print(28, 24, "               ");
    TV.print(32, 24, rcv_data_1);
}

void turnOnSPI(){
  #ifdef RCV_READY_PIN_D5
    PORTD &= ~B00100000; //PORTD : 0~7
  #endif
  #ifdef RCV_READY_PIN_D3
    PORTD &= ~B00001000;
  #endif
}

ISR(SPI_STC_vect)
{
  RCVD[pos++] = SPDR;
  if(pos > DATA_LENGTH)
  {
    RCVD[pos] = '\0';
    pos = 0;
    SPDR = 1;
  }
  else if(pos == DATA_LENGTH)
  {
    SPDR = 0;
  }
  else
  {
    SPDR = pos+1;
  }
  #ifdef RCV_READY_PIN_D5
  PORTD |= B00100000;
  #endif
  #ifdef RCV_READY_PIN_D3
  PORTD |= B00001000;
  #endif
}
Avamander commented 1 year ago

You are assembling your data structure in a very brittle way. The very least create a packed struct and avoid floating-point numbers. Especially if the two are both not the same architecture. After serialisation and deserialisation is done in a proper manner, eliminating those bugs, you can debug further.

ghost commented 1 year ago

my way(serialisation and deserialisation) did very well with simple SPI communication test. but I will consider using packed struct as you said.

and I want to debug float number by TVOut because my serial port is already using.