Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 22 of 22

Thread: Teensy 4.1 NON default SPI pins possible?

  1. #1

    Teensy 4.1 NON default SPI pins possible?

    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?

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,515
    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?

  3. #3
    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.

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,515
    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\ILI93 41_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.

  5. #5
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,528
    Which library? Some allow you to specify which spi buss to use

  6. #6
    Quote Originally Posted by KurtE View Post
    Which library? Some allow you to specify which spi buss to use
    the RF24 1.3.4 by TMRh20 library

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,528
    Quote Originally Posted by Mano1979 View Post
    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\ut ility\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.

  8. #8
    Thank you. i will try that.

    I'll post here again if it worked or not.

    Again, thank you for your time.

  9. #9
    Quote Originally Posted by KurtE View Post
    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\ut ility\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?

  10. #10
    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

  11. #11
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,528
    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.
    Click image for larger version. 

Name:	T4.1-Cardlike.jpg 
Views:	73 
Size:	244.3 KB 
ID:	20931
    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.

  12. #12
    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?

  13. #13
    I'm not sure if i'm checking for errors. i have never worked with these NRF modules before.

  14. #14
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,528
    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
         *
         * The size of data read is the fixed payload size, see getPayloadSize()
         *
         * @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.

  15. #15
    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?

  16. #16
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,528
    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.

  17. #17
    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!

  18. #18
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,528
    Again I don't use these much, but quick look at their datasheet: https://www.sparkfun.com/datasheets/...cation_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...

  19. #19
    ok i understand, thank you.

    I will try it and report back here.

    i really appreciate your help.

  20. #20
    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.

  21. #21
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,528
    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?

  22. #22
    Senior Member
    Join Date
    Sep 2015
    Location
    Taiwan, Asai. (Traditional Chinese)
    Posts
    173
    Quote Originally Posted by Mano1979 View Post

    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"));

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •