This is an example program that actually allows the car to race using the FRDM-TFC library!

Dependencies:   FRDM-TFC

Overview

This program is an example program that uses the FRDM-TFC library to actually permit a car using the FDRM-TFC shield + FRDM-KL25Z to race around a center line track.

Car Hookup

Motors

  • Code written assuming left motor hooked to B1(red)/B2(black) and right motor hooked to A1(red)/A2(black).

Battery

  • Be sure to hook positive (red) to 'Vbat' and negative (black) to 'Gnd'

Steering Servo

  • Servo must be hooked up with black wire innermost (away from LEDs).
  • Also be sure to mount servo on chassis with wire coming out the right side of the car.

Camera

  • Camera must be hooked up with black wire towards LEDs on the shield board.
  • Be sure to mount camera on tower with connector down towards the bottom.

Potentiometers (Pots)

  • Pots by default should have arrows pointing toward battery/motor hookup (for demo mods default).

Car Hardware Controls

DIP SWITCH CONTROLS:

  • Switch 1: Controls whether running main racing program (ON) or Demo program (OFF). Function of other 3 switches depend on this first switch.

RACING MODE (Switch 1 = ON)

  • Switch 2: Logging frame camera data to RAM while racing. Enable (ON) or Disable (OFF).
  • Switch 3: Risky / faster racing (ON); Conservative / slower race option (OFF). NOTE: Faster mode may cause car to fall off track. Needs tweaking...
  • Switch 4: Enable Start Gate Stop (ON) or Disable (OFF). NOTE: May not actually stop at start gate. Needs tweaking...
  • POTs 1,2 - controls nothing at the moment
  • PUSHBUTTON A - START car race!
  • PUSHBUTTON B - END CAR RACE / (while holding down when 'log frame data' active will also output terminal data gathered during race)
  • LEDs 1,2 light when Track is found
  • LEDs 0,3 light when Start Gate is Found

DEMO MODE 0 (Switch 1 = OFF; Switch 2 = OFF, Switch 3 = OFF)

  • PUSHBUTTON A - Light LED 0
  • PUSHBUTTON B - Light LED 3

DEMO MODE 1 (Switch 1 = OFF; Switch 2 = ON, Switch 3 = OFF)

  • POT 1 - Controls Servo: CCW = left; CW = right

DEMO MODE 2 (Switch 1 = OFF; Switch 2 = OFF, Switch 3 = ON)

  • POT 1 - Controls speed of right wheel: CCW = reverse; CW = forward
  • POT 2 - Controls speed of left wheel: CCW = reverse; CW = forward
  • NOTE In this mode the high pitched whine heard is of the H-bridge being active. To disable whine, briefly put into demo mode 1 above.

DEMO MODE 3 (Switch 1 = OFF; Switch 2 = ON, Switch 3 = ON)

  • Outputs camera data captured to terminal in CSV format, once every second.

Car Calibration

Serial Terminal

  • Download your favorite Terminal application (I use TeraTerm. Set it for 115200 baud, 8bit, none, 1bit.
  • But first you have to be sure that Windows mbed serial driver has been installed: Windows serial config.

Camera

  • If you want to hook up a scope, here are the pins of the camera interface from left to right: ground, 3.3V, SI, CLK, Analog_Out.
  • You want to hook up channel 1 between Analog_Out and Ground, channel 2 between SI and ground. SI can serve as your trigger.
  • Alternatively if you only want to use one channel, you can only hook up to Analog_Out and use triggering on the same channel.
  • Be sure to focus the camera properly. See demo video.
  • Be sure to prevent light noise on camera: Avoid Light Noise
  • More camera info

Servo/Steering

  • You will need to put the car into demo mode 1 and connect up a terminal to the serial port in order to get feedback on the values for your particular servo as hooked up. Then change MAX_STEER_LEFT and MAX_STEER_RIGHT in Spices.cpp with these values to tell the program how your servo is hooked up.
  • Here's a video where values are output to LCD to make it easier: http://youtu.be/fp5gyfEMf50

Speed Control

  • This program does not have proper speed control but does modify the speed slightly based on recent error results from the camera. It also modifies the differential speed to each wheel to have better control around curves.
  • While debugging your car you may want to lower the speed. See the function SpeedControl in Spices.cpp. There you can change which speed method you'd like to use. Currently is using value of 1, which gets maximum speed from TUNE_SPEED constant. Reduce to 0.4 or 0.5 when debugging car around the car (mainly to minimize crash forces!).

Strange Gotchas

Glitchy Motors

  • Apparently there is contention between TPM0_CH0 and OpenSDA micro that causes strange issues with Motors (PWM interference). This will cause glitches in motor activty when hooked up to USB only: Found contention

More Info

main.cpp

Committer:
redxeth
Date:
2014-04-20
Revision:
0:98e98e01a6ce

File content as of revision 0:98e98e01a6ce:

#include "mbed.h"
#include "TFC.h"

#include "common.h"
#include "Spices.h"


void TFC_TickerUpdate()
{
    int i;
 
    for(i=0; i<NUM_TFC_TICKERS; i++)
     {
        if(TFC_Ticker[i]<0xFFFFFFFF) 
        {
            TFC_Ticker[i]++;
        }
    }
}

void DemoProgram()
{
  uint32_t i,j,t = 0;
  float ReadPot0, ReadPot1;


  //This Demo program will look at the middle 2 switch to select one of 4 demo modes.
  //Let's look at the middle 2 switches
  switch((TFC_GetDIP_Switch()>>1)&0x03)
  {
  default:
  case 0 :
      //Demo mode 0 just tests the switches and LED's
      if(TFC_PUSH_BUTTON_0_PRESSED)
          TFC_BAT_LED0_ON;
      else
          TFC_BAT_LED0_OFF;
      
      if(TFC_PUSH_BUTTON_1_PRESSED)
          TFC_BAT_LED3_ON;
      else
          TFC_BAT_LED3_OFF;
      
      
/*      if(TFC_GetDIP_Switch()&0x01)
          TFC_BAT_LED1_ON;
      else
          TFC_BAT_LED1_OFF;
      
      if(TFC_GetDIP_Switch()&0x08)
          TFC_BAT_LED2_ON;
      else
          TFC_BAT_LED2_OFF; */
      
      break;
          
  case 1:
     TFC_HBRIDGE_DISABLE;
                    
     // if (TFC_HBRIDGE_ENABLED) {
        
    //    TFC_HBRIDGE_ENABLED = false;
    //  }

      //Demo mode 1 will just move the servos with the on-board potentiometers
      if(TFC_Ticker[0]>=20) // every 40mS...
      {
          TFC_Ticker[0] = 0; //reset the Ticker
          //update the Servos
          ReadPot0 = TFC_ReadPot(0);
          ReadPot1 = TFC_ReadPot(1);
          TFC_SetServo(0,ReadPot0);
          TFC_SetServo(1,ReadPot1);
          TERMINAL_PRINTF("Pot0 = %1.2f\r\n", ReadPot0);
      //    TERMINAL_PRINTF("Pot1 = %1.2f\r\n", ReadPot1);
      }
      //Let's put a pattern on the LEDs
      if(TFC_Ticker[1] >= 125) // every 250mS... cycle through LEDs
      {
          TFC_Ticker[1] = 0;
          t++;
          if(t>4)
          {
              t=0;
          }           
          TFC_SetBatteryLED_Level(t);
      }
      
      TFC_SetMotorPWM(0,0); //Make sure motors are off 
      TFC_HBRIDGE_DISABLE;

      break;
      
  case 2 :
      TFC_HBRIDGE_ENABLE;
     
      ReadPot0 = TFC_ReadPot(0);
      ReadPot1 = TFC_ReadPot(1);
 //     TERMINAL_PRINTF("Pot0 = %1.2f\n", ReadPot0);
 //     TERMINAL_PRINTF("Pot1 = %1.2f\n", ReadPot1);
      TFC_SetMotorPWM(ReadPot0,ReadPot1);
              
      //Let's put a pattern on the LEDs
      if(TFC_Ticker[1] >= 125)
          {
              TFC_Ticker[1] = 0;
                  t++;
                  if(t>4)
                  {
                      t=0;
                  }           
              TFC_SetBatteryLED_Level(t);
          }
      break;
  
  case 3 :
      //Demo Mode 3 will be in Freescale Garage Mode.  It will beam data from the Camera to the 
      //Labview Application
      //note that there are some issues 
      if(TFC_Ticker[0]>1000 && TFC_LineScanImageReady>0) // every 2s ...
          {
           TFC_Ticker[0] = 0;
           TFC_LineScanImageReady=0; // must reset to 0 after detecting non-zero
          
              if(t==0)
                  t=4;
              else
                  t--;
              
               TFC_SetBatteryLED_Level(t);
              
               for(i=0;i<8;i++) // print one line worth of data (128) from Camera 0
               {
                  for(j=0;j<16;j++)
                  {
                       
                       TERMINAL_PRINTF("0x%X",TFC_LineScanImage0[(i*16)+j]);
                      
                       if((i==7) && (j==15))  // when last data reached put in line return
                           TERMINAL_PRINTF("\r\n",TFC_LineScanImage0[(i*16)+j]);
                       else
                           TERMINAL_PRINTF(",",TFC_LineScanImage0[(i*16)+j]);
                      
                  }
                  wait_ms(10);
               }
              
     /*          for(i=0;i<8;i++) // print one line worth of data (128) from Camera 1 ??
               {
                    for(j=0;j<16;j++)
                     {
                       TERMINAL_PRINTF("0x%X",TFC_LineScanImage1[(i*16)+j]);
                      
                       if((i==7) && (j==15))  // when last data reached put in line return
                           TERMINAL_PRINTF("\r\n",TFC_LineScanImage1[(i*16)+j]);
                       else
                           TERMINAL_PRINTF(",",TFC_LineScanImage1[(i*16)+j]);
                      }   
                      
                      wait_ms(10);  
              }      */                                 
                  
          }
          


      break;
  } // end case

}

 
int main()
{
    // TERMINAL TYPE  
    PC.baud(115200); // works with Excel and TeraTerm 
    //PC.baud(9600); // works with USB Serial Monitor Lite: https://play.google.com/store/apps/details?id=jp.ksksue.app.terminal; doesn't work > 9600
    TFC_TickerObj.attach_us(&TFC_TickerUpdate,2000); // update ticker array every 2mS (2000 uS)
   
    TFC_Init();
    
    for(;;)
    {      
        //TFC_Task must be called in your main loop.  This keeps certain processing happy (I.E. Serial port queue check)
        //   TFC_Task();


        // If DIP switch 1 is high, then run MCP, else Demo program
        if(TFC_GetDIP_Switch()&0x01)
          // Run MCP
          MasterControlProgram();
        else      
          // Run Demo Program
          DemoProgram();
 
    } // end of infinite for loop
    
 
}