OpenEtherCATsociety / SOES

Simple Open Source EtherCAT Slave
Other
587 stars 251 forks source link

Inconsistent SPI Transmission with Sudden Jumps in Value #157

Closed Amir7RN closed 11 months ago

Amir7RN commented 1 year ago

I am encountering an issue with the SPI transmission in my code, and I would appreciate your guidance in resolving it. I am using a Raspberry Pi 4 and EVB-lan9252 in my setup.

I have noticed that the transmitted value via SPI is inconsistent. To isolate the issue, I simplified the code here and assigned a constant float value of 0.055f to a variable named "pitch." I intended to monitor the transmitted pitch value via SPI, expecting it to remain at a fixed value of 0.055f (which will be transmitted as a "55" integer). However, even in this simplified scenario, I still observe sudden jumps and peaks in the transmitted pitch value.

It's important to note that the pitch value is a float when assigned in the code, but it is received by SPI as an integer.

I have included the simplified code below:

#include <stdio.h>
#include "ecat_slv.h"
#include "utypes.h"
#include <bcm2835.h>

/* Application variables */
_Objects Obj;
_Mbuffer Mb;

// SPI Constants

void cb_get_inputs(void) {
}

void cb_set_outputs(void) {
}

void GPIO_init(void) {
    bcm2835_init();
}

int16_t received_dataf = 0;

void SPI_transmit_float(float data) {
   int16_t send_data = (int16_t)(data * 1000.0f);
   uint8_t send_data_high = (uint8_t)(send_data >> 8); // Get the high byte
   uint8_t send_data_low = (uint8_t)(send_data & 0xFF); // Get the low byte

   uint8_t received_data_high = bcm2835_spi_transfer(send_data_high);
   uint8_t received_data_low = bcm2835_spi_transfer(send_data_low);

   int16_t received_data_unit = (int16_t)((received_data_high << 8) | received_data_low);
   received_dataf = received_data_unit;
}

float pitch = 0.055f;

void cb_Data(float pitch) {
    SPI_transmit_float(pitch);
    Obj.in.IMU1_Pitch = received_dataf;
}

int main_run (void * arg) {
    static esc_cfg_t config =
   {
      .user_arg = "rpi4,cs0",
      .use_interrupt = 0,
      .watchdog_cnt = 150,
      .set_defaults_hook = NULL,
      .pre_state_change_hook = NULL,
      .post_state_change_hook = NULL,
      .application_hook = NULL,
      .safeoutput_override = NULL,
      .pre_object_download_hook = NULL,
      .post_object_download_hook = NULL,
      .rxpdo_override = NULL,
      .txpdo_override = NULL,
      .esc_hw_interrupt_enable = NULL,
      .esc_hw_interrupt_disable = NULL,
      .esc_hw_eep_handler = NULL,
      .esc_check_dc_handler = NULL,
   };

   printf ("Hello Main\n");
   GPIO_init();
   ecat_slv_init (&config);  

   while (1)
    {
        ecat_slv();
        cb_Data(pitch);
        printf("Pitch: %d\n", Obj.in.IMU1_Pitch);

    }

    return 0;

}

int main (void)
{

   main_run (NULL);
   return 0;
}

here is the output of SPI: it is constant 55 but there sudden peaks and jumps: pitch

Amir7RN commented 1 year ago

just changed the spi-mode in "esc_hw.c" line 478 to mode 3:

bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); ---> 
bcm2835_spi_setDataMode(BCM2835_SPI_MODE3);

and updated the code and utilizing bcm2835_spi_transfernb rather bcm2835_spi_transfer:

int16_t received_data = 0;

int16_t SPI_transmit_int(int data)
{

    int16_t spi_data[2];
    spi_data[0] = ESC_CMD_SERIAL_WRITE;
    spi_data[1] = (int16_t)(((data >> 8) & 0xFF));
    spi_data[2] = (int16_t)(data & 0xFF);
    bcm2835_spi_transfernb((char*)spi_data, (char*)spi_data, sizeof(spi_data));

    usleep(10);

    spi_data[0] = ESC_CMD_SERIAL_READ;   
    bcm2835_spi_transfernb((char*)spi_data, (char*)spi_data, sizeof(spi_data));

    int16_t received_data_unit = (int16_t)(((int32_t)spi_data[1] << 8) | (int32_t)spi_data[2]);
    received_data = received_data_unit;
    return received_data;

}

resolved my problem.

nakarlsson commented 1 year ago

Ok, good that it works.

I can’t find what mode or how to change it for LAN9252, have you?

For ET1100 it is an EEPROM setting.

nakarlsson commented 11 months ago

Close as fixed