Teensy 4.1 NON default SPI pins possible?

Status
Not open for further replies.

Mano1979

Active member
i have a servo controller board based on the Teensy 4.1.

Unfortunately the default SPI pins are used for servos.

I want to connect a NRF24L01 radio module and wondered if i can do so by utilising other pins. Pin 0 and 1 are in use for serial communication and 10,11,12 for servos.

What are my options and is it possible with an existing NRF24L01 arduino library?
 
The T_4.1 card shows pins for SPI1 bus :: pins 26,27,38,39

Not sure if the library accepts alternative to SPI as SPI1?
 
Yeah that is why i asked. i have tried before to change pins in libraries on arduino boards but that didn't work. so i wondered if it would work with the teensy since it has multiple dedicated SPI ports.
 
in the display libraries they have evolved to take the &SPI as a param in some fashion and they work with that passing in the pointer to an SPI object that may be SPI or SPI1 based. Not sure about the NRF library.

If not then following the lead in TeensyDuino included :: ...\hardware\teensy\avr\libraries\ILI9341_t3\ILI9341_t3.cpp
like :: ILI9341_t3::ILI9341_t3(uint8_t cs, uint8_t dc, uint8_t rst, uint8_t mosi, uint8_t sclk, uint8_t miso)

May be a start ? - NRF lib not included in TD so can't see easily what the one there looks like.
 
the RF24 1.3.4 by TMRh20 library
I have not done so, but it looks like you can edit the library to maybe use SPI1 (or SPI2).

This is NOT my preferred way to customize libraries like this, but if you look at where this library is installed, in my case it is at:
C:\Users\kurte\Documents\Arduino\libraries\RF24

Obviously your full path will be different.... But under this directory is a set of directories with configuration files for different platforms.
So again in my case if I edit the file: C:\Users\kurte\Documents\Arduino\libraries\RF24\utility\Teensy\RF24_arch_config.h

I am guessing that if I change the like:
Code:
#define _SPI SPI
to
Code:
#define _SPI SPI1
It will probably use the SPI object... But again I have not tested this.
 
I have not done so, but it looks like you can edit the library to maybe use SPI1 (or SPI2).

This is NOT my preferred way to customize libraries like this, but if you look at where this library is installed, in my case it is at:
C:\Users\kurte\Documents\Arduino\libraries\RF24

Obviously your full path will be different.... But under this directory is a set of directories with configuration files for different platforms.
So again in my case if I edit the file: C:\Users\kurte\Documents\Arduino\libraries\RF24\utility\Teensy\RF24_arch_config.h

I am guessing that if I change the like:
Code:
#define _SPI SPI
to
Code:
#define _SPI SPI1
It will probably use the SPI object... But again I have not tested this.

I have tried this but it does not work. Is there a way to manually declare the pins used? just like with software SPI?
Or do you have any other ideas?
 
I managed to get it working by defining the miso and sck pin manually.

But now the data (an array of 13 values) is somewhat scrambled. Some values are beeing displayed (serial monitor) correctly, but others are combined in the weirdest places, and the rest of the array printout say 0,0,0,0,0,0,0

So here an example of what i receive and what it should be:
What i get...
311,654241,630,66528928,665383642,0,0,0,0,0,0,0,0

What it should be...
311,426,630,201,324,103,1000,1000,1000,1000,1,0,2
 
Again without seeing any code and setup... There is very little any of us can do to try to help.
Example are you using the default pins for SPI1 or alternative. My guess is alternative. I know that the official Card with front only does not show which of the pins is the default ones.
T4.1-Cardlike.jpg
But hopefully my unofficial one shows it. That pin 1 is default MISO pin for SPI1...

So to use pin 39 instead you would need to do the: SPI1.setMISO(39);

As for numbers you get or don't get.. Again there is no information on where these numbers come from. Are they being sent properly? What communications setup are you using?

Are you checking for status? Maybe it did not send correctly and was an error?

But again just throwing darts.
 
Your absolutely right, my bad. I should have posted the code.

here is the receiving sketch (running on the teensy):
Code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(37, 38); // CE, CSN
const byte address[6] = "00001";
int gotArray[13];

void setup() {
SPI1.setCS(38);
SPI1.setMISO(39);
SPI1.begin();

Serial.begin(115200);
Serial.println("starting....");
radio.begin();
radio.openReadingPipe(0, address);   //Setting the address at which we will receive the data
radio.setPALevel(RF24_PA_MIN);       //You can set this as minimum or maximum depending on the distance between the transmitter and receiver.
radio.startListening();              //This sets the module as receiver
}
void loop()
{
  delay(1);
  while(radio.available()){ 
    radio.read( &gotArray, sizeof(gotArray) ); 
    Serial.print("Recieved array:\n"); 
    for (byte i=0; i<13; i++){
      Serial.print(gotArray[i]);
      Serial.print(",");
    }
    Serial.println("\n");
   }
  
 //delay(20);
}

and this is the code running on an arduino mega2560:
Code:
#include <Arduino.h>
#include <EEPROM.h>
#include <avr/wdt.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN
const byte address[6] = "00001";    //Choose a unique adress (should be the same on the receiver side)

/*
  U8g2lib Example Overview:
    Frame Buffer Examples: clearBuffer/sendBuffer. Fast, but may not work with all Arduino boards because of RAM consumption
    Page Buffer Examples: firstPage/nextPage. Less RAM usage, should work with all Arduino boards.
    U8x8 Text Only Example: No RAM usage, direct communication with display controller. No graphics, 8x8 Text only.
    
*/
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 18 /* A4 */ , /* data=*/ 16 /* A2 */, /* CS=*/ 17 /* A3 */, /* reset=*/ U8X8_PIN_NONE);   // Uncomment for arduino MEGA2560
//U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 10, /* reset=*/ 8);                                         // Uncomment for arduino UNO, NANO

const uint8_t spot_bitmap[] = {
  0x00, 0x00, 0x7F, 0xF8, 0x00, //                  ############      
  0x00, 0x3F, 0x80, 0x74, 0x00, //           #######        ### #     
  0x03, 0xE0, 0x00, 0x7A, 0x00, //       #####              #### #    
  0x7C, 0x00, 0x00, 0x66, 0x00, //  #####                   ##  ##    
  0x83, 0xFE, 0x03, 0xE2, 0x00, // #     #########       #####   #    
  0x80, 0x1E, 0x07, 0x21, 0x00, // #          ####      ###  #    #   
  0xFF, 0x0F, 0x9C, 0x39, 0x00, // ########    #####  ###    ###  #   
  0xF4, 0x88, 0x70, 0x7C, 0x80, // #### #  #   #    ###     #####  #  
  0x6A, 0x48, 0x20, 0x8C, 0x80, //  ## # #  #  #     #     #   ##  #  
  0x7A, 0x4F, 0x1F, 0x06, 0x40, //  #### #  #  ####   #####     ##  # 
  0x35, 0x2F, 0x0C, 0x07, 0x20, //   ## # #  # ####    ##       ###  #
  0x1D, 0x59, 0x88, 0x03, 0xA0, //    ### # # ##  ##   #         ### #
  0x07, 0xF0, 0xC4, 0x03, 0xA0, //      #######    ##   #        ### #
  0x03, 0xF0, 0xE2, 0x01, 0xE0, //       ######    ###   #        ####
  0x07, 0xC1, 0xF1, 0x07, 0xC0, //      #####     #####   #     ##### 
  0x0F, 0x83, 0xF9, 0x0F, 0x80, //     #####     #######  #    #####  
  0x0F, 0x07, 0xB9, 0x1E, 0x00, //     ####     #### ###  #   ####    
  0x1C, 0x07, 0x9D, 0x1C, 0x00, //    ###       ####  ### #   ###     
  0x38, 0x03, 0x3E, 0x38, 0x00, //   ###         ##  #####   ###      
  0x78, 0x00, 0x7E, 0x78, 0x00, //  ####            ######  ####      
  0xF0, 0x00, 0xF8, 0x78, 0x00, // ####            #####    ####      
  0xF0, 0x01, 0xE0, 0x78, 0x00, // ####           ####      ####      
  0x70, 0x01, 0xC0, 0x30, 0x00, //  ###           ###        ##       
  0x20, 0x03, 0x80, 0x00, 0x00, //   #           ###                  
  0x00, 0x07, 0x00, 0x00, 0x00, //              ###                   
  0x00, 0x0F, 0x00, 0x00, 0x00, //             ####                   
  0x00, 0x0F, 0x00, 0x00, 0x00, //             ####                   
  0x00, 0x0F, 0x00, 0x00, 0x00, //             ####                   
  0x00, 0x06, 0x00, 0x00, 0x00, //              ##                                                                                              
};

char pot1[4];
char pot2[4];
char pot3[4];
char pot4[4];
char pot5[4];
char pot6[4];
char gaitVersion[4];
char joyLX[4];
char joyLY[4];
char joyRX[4];
char joyRY[4];

int gait = 0;
int Array[13];

int LXmid;
int LYmid;
int LYup;
int LYdown;
int LXleft;
int LXright;
int RXmid;
int RYmid;
int RYup;
int RYdown;
int RXleft;
int RXright;

int LY;
int LX;
int RY;
int RX;

//WRITE CALIBRATIONS DATA TO THE EEPROM IN 2 BYTES
void EEPROMWriteInt(int address, int value)
{
  byte two = (value & 0xFF);
  byte one = ((value >> 8) & 0xFF);
  
  EEPROM.update(address, two);
  EEPROM.update(address + 1, one);
}

 //READ CALOBRATION DATA FROM THE EEPROM IN 2 BYTE'S PER VARIABLE
int EEPROMReadInt(int address)
{
  long two = EEPROM.read(address);
  long one = EEPROM.read(address + 1);
 
  return ((two << 0) & 0xFFFFFF) + ((one << 8) & 0xFFFFFFFF);
}

void writeDisplay(){
  u8g2.clearBuffer();                           // clear the internal memory
  u8g2.setFont(u8g2_font_sirclivethebold_tr);   // choose a suitable font
  u8g2.drawStr(86,7,"Spot");                    // write text to display
  u8g2.drawBitmap( 88, 10, 5, 29, spot_bitmap); // write SpotMicro image to display
  u8g2.setFont(u8g2_font_5x7_tr);   // choose a suitable font u8g2_font_6x10_tf
  if(digitalRead(7)== HIGH){
    u8g2.drawStr(82,13,"A");                    // Autonomous Mode
  }else{
    u8g2.drawStr(82,13,"M");                    // Manual Control
  }
  if(digitalRead(6)==LOW){
    u8g2.drawStr(82,21,"O");                    // Servo's Powered
  }else{
    u8g2.drawStr(82,21,"X");                    // Servo's Off
  }
  u8g2.drawStr(82,29,gaitVersion);
  
  u8g2.setFont(u8g2_font_ncenB08_tr);
// LEFT JOYSTICK                X axis                    Y axis
  u8g2.drawDisc(34-(map(LX,LXright,LXleft,4,13)), map(LY,LYup,LYdown,4,13), 4);
  u8g2.drawHLine(15, 0, 5);     
  u8g2.drawHLine(15, 34, 5);
  u8g2.drawVLine(0, 15, 5);
  u8g2.drawVLine(34, 15, 5);

  u8g2.drawHLine(15, 5, 5);
  u8g2.drawHLine(15, 29, 5);
  u8g2.drawVLine(5, 15, 5);
  u8g2.drawVLine(29, 15, 5);

  u8g2.drawHLine(15, 10, 5);
  u8g2.drawHLine(15, 24, 5);
  u8g2.drawVLine(10, 15, 5);
  u8g2.drawVLine(24, 15, 5);

  u8g2.drawHLine(15, 15, 5);
  u8g2.drawHLine(15, 19, 5);
  u8g2.drawVLine(15, 15, 5);
  u8g2.drawVLine(19, 15, 5);

//RIGHT JOYSTICK                X axis                    Y axis
  u8g2.drawDisc((34-(map(RX,RXright,RXleft,4,13)))+45, map(RY,RYup,RYdown,4,13), 4);
  u8g2.drawHLine(60, 0, 5);
  u8g2.drawHLine(60, 34, 5);
  u8g2.drawVLine(45, 15, 5);
  u8g2.drawVLine(79, 15, 5);

  u8g2.drawHLine(60, 5, 5);
  u8g2.drawHLine(60, 29, 5);
  u8g2.drawVLine(50, 15, 5);
  u8g2.drawVLine(74, 15, 5);

  u8g2.drawHLine(60, 10, 5);
  u8g2.drawHLine(60, 24, 5);
  u8g2.drawVLine(55, 15, 5);
  u8g2.drawVLine(69, 15, 5);

  u8g2.drawHLine(60, 15, 5);
  u8g2.drawHLine(60, 19, 5);
  u8g2.drawVLine(60, 15, 5);
  u8g2.drawVLine(64, 15, 5);

  u8g2.drawStr(0,44,"Height:");         // write something to the internal memory
  u8g2.drawStr(0,54,"ShiftX:");         // write something to the internal memory
  u8g2.drawStr(0,64,"ShiftY:");         // write something to the internal memory
  u8g2.drawStr(68,44,"Yaw:");           // write something to the internal memory
  u8g2.drawStr(68,54,"Pitch:");         // write something to the internal memory
  u8g2.drawStr(68,64,"Roll:");          // write something to the internal memory
  u8g2.drawStr(44,44,pot1);             // write something to the internal memory
  u8g2.drawStr(44,54,pot2);             // write something to the internal memory
  u8g2.drawStr(44,64,pot3);             // write something to the internal memory
  u8g2.drawStr(110,44,pot4);            // write something to the internal memory
  u8g2.drawStr(110,54,pot5);            // write something to the internal memory
  u8g2.drawStr(110,64,pot6);            // write something to the internal memory
  u8g2.sendBuffer();                    // transfer internal memory to the display
}

void joystickCalib(){
  u8g2.clear();                               // clear the display
  u8g2.drawStr(0,20,"CALIBRATE JOYSTICK");    // write something to the internal memory
  u8g2.drawStr(0,30,"You've got 3 seconds");
  u8g2.drawStr(0,40,"for moves. READY?");
  u8g2.sendBuffer();                          // transfer internal memory to the display
  delay(5000);
  u8g2.clear();
  u8g2.drawStr(0,20,"Center L-joystick");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  LXmid=analogRead(A9);
  delay(2);
  LYmid=analogRead(A8);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  Serial.println(LXmid);
  Serial.println(LYmid);
  u8g2.drawStr(0,20,"Push L-joystick UP");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  LYup=analogRead(A8);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  Serial.println(LYup);
  u8g2.drawStr(0,20,"Push L-joystick DOWN");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  LYdown=analogRead(A8);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  Serial.println(LYdown);
  u8g2.drawStr(0,20,"Push L-joystick LEFT");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  LXleft=analogRead(A9);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  Serial.println(LXleft);
  u8g2.drawStr(0,20,"Push L-joystick RIGHT");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  LXright=analogRead(A9);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  Serial.println(LXright);
  
  u8g2.clear();
  u8g2.drawStr(0,20,"Center R-joystick");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  RXmid=analogRead(A11);
  delay(2);
  RYmid=analogRead(A10);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  u8g2.drawStr(0,20,"Push R-joystick UP");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  RYup=analogRead(A10);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  u8g2.drawStr(0,20,"Push R-joystick DOWN");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  RYdown=analogRead(A10);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  u8g2.drawStr(0,20,"Push R-joystick LEFT");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  RXleft=analogRead(A11);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  u8g2.drawStr(0,20,"Push R-joystick RIGHT");
  u8g2.sendBuffer();
  delay(3000);
  u8g2.clear();
  RXright=analogRead(A11);
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF

  //SEND CALIBRATION DATA TO EEPROMWriteInt() FUNCTION FOR WRITING TO EEPROM
  EEPROMWriteInt(2, LXmid);
  EEPROMWriteInt(5, LYmid);
  EEPROMWriteInt(10, LYup);
  EEPROMWriteInt(15, LYdown);
  EEPROMWriteInt(20, LXleft);
  EEPROMWriteInt(25, LXright);
  EEPROMWriteInt(30, RXmid);
  EEPROMWriteInt(35, RYmid);
  EEPROMWriteInt(40, RYup);
  EEPROMWriteInt(45, RYdown);
  EEPROMWriteInt(50, RXleft);
  EEPROMWriteInt(55, RXright);
  EEPROMWriteInt(0, 1); //MARK THAT EEPROM HAS BEEN WRITTEN AT LEAST ONCE
  setup();//reboot(); //REBOOT THE ARDUINO SO THE VALUES ARE READ FRESH OUT OF THE EEPROM (NOT WORKING YET)
}

void reboot() {
  wdt_disable();
  wdt_enable(WDTO_15MS);
  while (1) {}
}

void setup(void) {
  Serial.begin(115200);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(A12, OUTPUT);
  
  u8g2.begin();
  u8g2.clearBuffer();                           // clear the internal memory
  u8g2.setFont(u8g2_font_sirclivethebold_tr);   // choose a suitable font
  u8g2.drawStr(20,17,"SpotMicro");                    // write text to display
  u8g2.drawBitmap( 45, 20, 5, 29, spot_bitmap); // write SpotMicro image to display
  u8g2.drawStr(18,57,"Remote v1.0");
  u8g2.sendBuffer();
  delay(5000);
  if(EEPROM.read(0) == 255){
    u8g2.clearBuffer();                             // clear the internal memory
    u8g2.setFont(u8g2_font_ncenB08_tr);             // choose a suitable font
    u8g2.clear();                                   // clear the display
    u8g2.drawStr(0,20,"Joysticks are not yet");     // write something to the internal memory
    u8g2.drawStr(0,30,"calibrated! Push 1st");
    u8g2.drawStr(0,40,"button to do so anytime");
    u8g2.drawStr(1,57,"|");
    u8g2.drawStr(2,57,"|");
    u8g2.drawStr(0,64,"V");
    u8g2.sendBuffer();                              // transfer internal memory to the display;
    delay(5000);
  }
  if(EEPROM.read(0) == 1){
    u8g2.clearBuffer();                             // clear the internal memory
    u8g2.setFont(u8g2_font_ncenB08_tr);             // choose a suitable font
    u8g2.clear();                                   // clear the display
    u8g2.drawStr(0,20,"To re-calibrate the");       // write something to the internal memory
    u8g2.drawStr(0,30,"joysticks, at anytime");
    u8g2.drawStr(0,40,"push the 1st button.");
    u8g2.drawStr(1,57,"|");
    u8g2.drawStr(2,57,"|");
    u8g2.drawStr(0,64,"V");
    u8g2.sendBuffer();                              // transfer internal memory to the display;
    delay(4000);
    u8g2.clearBuffer();                             // clear the internal memory
    u8g2.clear();                                   // clear the display
    u8g2.drawStr(0,20,"To erase the");              // write something to the internal memory
    u8g2.drawStr(0,30,"calibration in eeprom,");
    u8g2.drawStr(0,40,"push the 2nd button.");
    u8g2.drawStr(59,57,"|");
    u8g2.drawStr(60,57,"|");
    u8g2.drawStr(58,64,"V");
    u8g2.sendBuffer(); 
    EEPROM.write(0, 2);                             // Make sure the calibration messages aren't shown
    delay(4000);
  }                                                 // after the 2nd reboot.
     
  //READ CALIBRATION VALUES FROM EEPROM
  LXmid=EEPROMReadInt(2);
  LYmid=EEPROMReadInt(5);
  LYup=EEPROMReadInt(10);
  LYdown=EEPROMReadInt(15);
  LXleft=EEPROMReadInt(20);
  LXright=EEPROMReadInt(25);
  RXmid=EEPROMReadInt(30);
  RYmid=EEPROMReadInt(35);
  RYup=EEPROMReadInt(40);
  RYdown=EEPROMReadInt(45);
  RXleft=EEPROMReadInt(50);
  RXright=EEPROMReadInt(55);
  
  Serial.println(LXmid);
  Serial.println(LYmid);
  Serial.println(LYup);
  Serial.println(LYdown);
  Serial.println(LXleft);
  Serial.println(LXright);
  
  
  radio.begin();                  //Starting the Wireless communication
  radio.openWritingPipe(address); //Setting the address where we will send the data
  radio.setPALevel(RF24_PA_MIN);  //You can set it as minimum or maximum depending on the distance between the transmitter and receiver.
  radio.stopListening();          //This sets the module as transmitter
}

void loop() {
  //FIRST BUTTON BETWEEN JOYSTICKS ACTIVATES JOYSTICK CALIBRATION
  if(digitalRead(5)== LOW){       //button pressed (JOYSTICK CALIBRATION)
    joystickCalib();
  }
  if(digitalRead(4)== LOW){       //button pressed (ERASE EEPROM)
    for(int i=0;i<100;i++){
      EEPROM.write(i, 255);
    }
  }
  if(digitalRead(3)== LOW){       //CHANGE WALKING GAIT)
    if(gait<2){                   //SET TO A MAX OF 3 DIFFERENT WALKING GAITS
      gait++;                     //GO TO THE NEXT GAIT (VALUE IS SENT TO THE ROBOT)
    }else{
      gait = 0;                   //IF GAIT IS HIGHER THAN 2 (3RD GAIT), RESET TO FIRST GAIT 
    }
    delay(300);
  }

  //READ TOGGLE SWITCHES
  int toggle1 = digitalRead(7);       //HIGH=Autonomous LOW=Manual control
  int toggle2 = digitalRead(6);       //HIGH=Servo-power-on LOW=Servo-power-off
  
  //READ KNOB VALUES 3 TIMES AND CALCULATE AVERAGE
  int temp11=analogRead(A0);
  int temp12=analogRead(A0);
  int temp13=analogRead(A0);
  int temp1=(temp11+temp12+temp13)/3;
  int temp21=analogRead(A1);
  int temp22=analogRead(A1);
  int temp23=analogRead(A1);
  int temp2=(temp21+temp22+temp23)/3;
  int temp31=analogRead(A2);
  int temp32=analogRead(A2);
  int temp33=analogRead(A2);
  int temp3=(temp31+temp32+temp33)/3;
  int temp41=analogRead(A3);
  int temp42=analogRead(A3);
  int temp43=analogRead(A3);
  int temp4=(temp41+temp42+temp43)/3;
  int temp51=analogRead(A4);
  int temp52=analogRead(A4);
  int temp53=analogRead(A4);
  int temp5=(temp51+temp52+temp53)/3;
  int temp61=analogRead(A5);
  int temp62=analogRead(A5);
  int temp63=analogRead(A5);
  int temp6=(temp61+temp62+temp63)/3;

  //CONVERSION FOR WRITING KNOB VALUES TO DISPLAY
  sprintf(pot1, "%d", temp1);         //height
  sprintf(pot2, "%d", temp2);         //shiftX
  sprintf(pot3, "%d", temp3);         //shiftY
  sprintf(pot4, "%d", temp4);         //roll
  sprintf(pot5, "%d", temp5);         //pitch
  sprintf(pot6, "%d", temp6);         //yaw
  sprintf(gaitVersion, "%d", gait+1);
  
  //READ JOYSTICK VALUES 3 TIMES AND TAKE THE AVERAGE
  int potA=(analogRead(A8));
  int potA1=(analogRead(A8));
  int potA2=(analogRead(A8));
  potA=(potA+potA1+potA2)/3;
  int potB=(analogRead(A9));
  int potB1=(analogRead(A9));
  int potB2=(analogRead(A9));
  potB=(potB+potB1+potB2)/3;
  int potC=(analogRead(A10));
  int potC1=(analogRead(A10));
  int potC2=(analogRead(A10));
  potC=(potC+potC1+potC2)/3;
  int potD=(analogRead(A11));
  int potD1=(analogRead(A11));
  int potD2=(analogRead(A11));
  potD=(potD+potD1+potD2)/3;

  //CONVERT JOYSTICK VALUES TO VALUES BETWEEN 0 AND 2000, 1000 BEING THE CENTRE
  if(potA > LYmid){
    LY = map(potA, LYmid, LYdown, 1000, 2000);
  }
  else {
    LY = map(potA, LYup, LYmid, 0, 1000);
  }
  if(potB > LXmid){
    LX = map(potB, LXmid, LXleft, 1000, 2000);
  }
  else {
    LX = map(potB, LXright, LXmid, 0, 1000);
  }
  if(potC > RYmid){
    RY = map(potC, RYmid, RYdown, 1000, 2000);
  }
  else {
    RY = map(potC, RYup, RYmid, 0, 1000);
  }
  if(potD > RXmid){
    RX = map(potD, RXmid, RXleft, 1000, 2000);
  }
  else {
    RX = map(potD, RXright, RXmid, 0, 1000);
  }

  //PUTTING ALL VALUES IN AN ARRAY FOR SENDING IT OVER NRF24L01 RADIO
  Array[0]=temp1;
  Array[1]=temp2;
  Array[2]=temp3;
  Array[3]=temp4;
  Array[4]=temp5;
  Array[5]=temp6;
  Array[6]=2000-LY;     //INVERTED VALUES (DOWN IS 0 AND UP IS 2000)
  Array[7]=2000-LX;     //INVERTED VALUES (LEFT IS 0 AND RIGHT IS 2000)
  Array[8]=2000-RY;;    //INVERTED VALUES (DOWN IS 0 AND UP IS 2000)
  Array[9]=2000-RX;     //INVERTED VALUES (LEFT IS 0 AND RIGHT IS 2000)
  Array[10]=toggle1;
  Array[11]=toggle2;
  Array[12]=gait;
  
  radio.write( &Array, sizeof(Array));
  digitalWrite(A12, HIGH); //LED ON
  delay(1);
  digitalWrite(A12, LOW); //LED OFF
  for(int i=0;i<13;i++){
    Serial.print(Array[i]);
    Serial.print(",");
  }
  Serial.print("\n");
  writeDisplay();
  //delay(20); 
}

I used to run the receiver code on another arduino mega2560 and that one received the Array just fine. so i may assume the code is right.
My thought was that it might be a timing issue, since the arduino is 16mhz and the teensy 600mhz?
 
Note, I have never used this library or probably these modules... I have done a little with Radiohead with other modules...
So maybe someone who uses this library might be able to help.

But my first suspect might be your code:
Code:
while(radio.available()){ 
    radio.read( &gotArray, sizeof(gotArray) ); 
    Serial.print("Recieved array:\n"); 
    for (byte i=0; i<13; i++){
      Serial.print(gotArray[i]);
      Serial.print(",");
    }
    Serial.println("\n");
   }
Things I might suspect:

a) What size of data is read? If you look at their header file at the description of Read you see:
Code:
    /**
     * Read the available payload
     *
[COLOR="#FF0000"]     * The size of data read is the fixed payload size, see getPayloadSize()[/COLOR]
     *
     * @note I specifically chose 'void*' as a data type to make it easier
     * for beginners to use.  No casting needed.
     *
     * @note No longer boolean. Use available to determine if packets are
     * available. Interrupt flags are now cleared during reads instead of
     * when calling available().
     *
     * @param buf Pointer to a buffer where the data should be written
     * @param len Maximum number of bytes to read into the buffer
     *
     * @code
     * if(radio.available()){
     *   radio.read(&data,sizeof(data));
     * }
     * @endcode
     * @return No return value. Use available().
     */
So what is the payload that your module can handle or setup for?

b) Things like: int gotArray[13];
When you use a generic data type like int, it will depend on what processor you are compiling on. So for example on the T4, these will be 4 bytes. On AVR these are probably 2 bytes.
In addition to this. Not all processors order the bytes in the same order. Example 16 bit numbers. Some may put the byte with the high order bits first, some may put the low order bits first.

You might be fine on this part, but sometimes to be processor independent, one might define exactly the byte layouts of their packets.

Maybe will get lucky and data size of read and variables is the issue, otherwise one might have to dig more into how the library works.
 
ok, question A:
payload size is 32.
what i'm setup for? no idea. i thought that "sizeof(data)" handled this automatically

and B:
How do i tell the mega 2560 (sender) to send the data is 4 bytes? or the teensy to convert 2 to 4 bytes?
The Low bits first or high bits first, could be a thing. but then, why are some values empty?
 
a) 13*4=52 bytes. As for what are you configured for? I don't know, I would call their function getPayloadSize and print it out to see.

b) As for data sizes between the two processors, the best thing to do is decide on what size you need and is it signed or unsigned?
Example if you really do want 4 byte signed values, then on both processors you should use int32_t as the type. If 16 bites is good enough int16_t
if unsigned 16, use: uint16_t

That way you are telling the system exactly what type of number you are using.

Edit: On a) your sizeof(), lets the system know that if the payload size of the connection is > than the size of your variable only transfer your size bytes of data to your buffer.
 
Aaah, ok that makes sense.

So if i understand you right, i must run that "getPayloadSize"command on both systems and compare them?
I will make the appropriate adjustments to the code to make sure both systems use the same int-type. Thank you!
 
Again I don't use these much, but quick look at their datasheet: https://www.sparkfun.com/datasheets/Wireless/Nordic/nRF24L01P_Product_Specification_1_0.pdf

I believe the playload can be 1-32 bytes...

So for example if you need to send 13 4 byte integers, this will not fit in one packet. Will take two. How you split this up maybe up to you.
You could send 32 bytes on first packet and 20 bytes on second... But of course that means on your reads you need to understand which packet you are on and potentially check to see if you are properly aligned on knowing which part you are receiving...
 
I changed all values to sent and all values to receive to uint16_t and it worked!
Though the speed is a bit unreliable. The time between the received array is not the same every time, and overall a bit slow.
Might you have an idea what the problem is here, then i would be happy to hear it, but if not, i'm already very thankful that you helped me to get it working.
 
Again sorry, I don't use this library...

But things I would look at are things like: I believe you can set how fast the device should transmit...
setDataRate (maybe?)

I would look at what type of protocol is setup, and if that is right for what you want.
A lot of these maybe default to a complete handshake... That is when the one sends the packet, it will wait for so long to get an ACK back, if it does not it might repeat So many time before it errors out.

Sometimes you have the option, send once and hope it is received. Sort of like the difference between TCP and UDP... So for example you are wanting to send things like joystick data as fast as possible and it does not really matter if an occasional one is lost, than there may be a way to do faster transfers.

maybe here difference between: write and writeFast?
 
I used to run the receiver code on another arduino mega2560 and that one received the Array just fine. so i may assume the code is right.
My thought was that it might be a timing issue, since the arduino is 16mhz and the teensy 600mhz?

Hello,
I use nRF24 module a lot too, the library is fine with LC, but I've not tested with T4 yet.
Not sure if the RF24 library did recognize it as using SPI pin, or soft SPI
if the latter, 600mhz bit bang could possibly be too fast for your nRF module, you try to compile your code at 24Mhz(since there is the option) to see if it works better

also you can try to see if the radio is able to start up fine?
Code:
  if (radio.begin()) {
    Serial.println(F("\nSTART SUCCESS\n"));
    // do something();
  }
  else
    Serial.println(F("\nSTART FAILURE\n"));
 
Status
Not open for further replies.
Back
Top