Official library for the FRDM-TFC shield

Dependents:   TFC-TEST TFC-RACING-DEMO TFC-RACING-DEMO TFC-RACING-FSLMENTORMATTERS ... more

Overview

This library is an example driver for the FRDM-TFC shield that can be used for with MBED compiler. Documentation for the hardware can be found here

https://community.freescale.com/docs/DOC-93914

Note that the current videos on that page pertain to the codewarrior example projects hosted on google code, not the library presented here. While the code is very similiar, there are some differences. New videos will be posted for the MBED libraries as the code bases will eventually merge

Also note that this is just the raw library. The example program that uses the code is here:

http://mbed.org/users/redxeth/code/TFC-TEST/

IMPORTANT

There is a bug with firmware "mbed_if_v2.0_frdm_kl25Z ". It seems to hold the I/O pin PORTC1 (FTM0 - Channel 0 on J10 Pin 12) high. This prevents the PWM signal for one of the motor drivers from working correctly.

Page 4 of the FRDM-LK25Z board shows the OpenSDA connected to this net via resistor R24. Remove this resistor on your freedom board.

This was verified to be in the SDA firmware as the debug firmware used for Codewarrior use (DEBUG-APP_Pemicro_v102.SDA) does not have this issue.

Example Main.cpp

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

 
//This macro is to maintain compatibility with Codewarrior version of the sample.   This version uses the MBED libraries for serial port access
Serial PC(USBTX,USBRX);

#define TERMINAL_PRINTF     PC.printf

 
 //This ticker code is used to maintain compability with the Codewarrior version of the sample.   This code uses an MBED Ticker for background timing.
 
#define NUM_TFC_TICKERS 4

Ticker TFC_TickerObj;
 
volatile uint32_t TFC_Ticker[NUM_TFC_TICKERS];
 
void TFC_TickerUpdate()
{
    int i;
 
    for(i=0; i<NUM_TFC_TICKERS; i++)
     {
        if(TFC_Ticker[i]<0xFFFFFFFF) 
        {
            TFC_Ticker[i]++;
        }
    }
}
 
 
int main()
{
    uint32_t i,t = 0;
  
    PC.baud(115200);
    TFC_TickerObj.attach_us(&TFC_TickerUpdate,2000);
   
    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();

            //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:
                
                //Demo mode 1 will just move the servos with the on-board potentiometers
                if(TFC_Ticker[0]>=20)
                {
                    TFC_Ticker[0] = 0; //reset the Ticker
                    //Every 20 mSeconds, update the Servos
                    TFC_SetServo(0,TFC_ReadPot(0));
                    TFC_SetServo(1,TFC_ReadPot(1));
                }
                //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);
                }
                
                TFC_SetMotorPWM(0,0); //Make sure motors are off
                TFC_HBRIDGE_DISABLE;
            

                break;
                
            case 2 :
                
                //Demo Mode 2 will use the Pots to make the motors move
                TFC_HBRIDGE_ENABLE;
               
                TFC_SetMotorPWM(TFC_ReadPot(0),TFC_ReadPot(1));
                
                        
                //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
                
                
                if(TFC_Ticker[0]>50 && TFC_LineScanImageReady>0)
                    {
                     TFC_Ticker[0] = 0;
                     TFC_LineScanImageReady=0;
                     TERMINAL_PRINTF("\r\n");
                     TERMINAL_PRINTF("L:");
                     
                        if(t==0)
                            t=4;
                        else
                            t--;
                        
                         TFC_SetBatteryLED_Level(t);
                        
                         // camera 1
                         for(i=0;i<128;i++)
                         {
                               TERMINAL_PRINTF("%X,",TFC_LineScanImage0[i]);
                         }
                        
                        // camera 2
                         for(i=0;i<128;i++)
                         {
                                 if(i==127)
                                     TERMINAL_PRINTF("%X\r\n",TFC_LineScanImage1[i]);
                                 else
                                     TERMINAL_PRINTF("%X,",TFC_LineScanImage1[i]);
                           
                         }
                    }
                 
                break;
            }
    }
    
 
}

Implementation Notes

The goal of the this library was to provide an easy to use API for the FRDM-TFC hardware that would give one a good start in getting a car working. There are only a couple of function calls needed to make the components on the care work. The library is implemented as a standard C API. While most of the MBED code is provided as a C++, the decision to use a C only API was done for the following reasons:

  • Some of the advantages of a C++ class really don't apply in this case. Since there would only be a single instance of the class library, there is no reason to wrap the functions in a class.
  • The library tightly integrated to synchronized different components in the interrupts routines. I.E. Camera acquisition is synced to the servo period. To accomplished this we had to write the code in raw C and write our own interrupt routines. Tieing these to a c++ class really didn't make sense.
  • Since many users also use an "offline" compiler, (I.E. Codewarrior) it was a design requirement that the the same code/API could be easy moved to the Codewarrior environment.
  • Even though the MBED libraries provide classes for PWM that could be used for the servos and drive motor controller, we had to write our own code for the internal TPM units as we needed some special features (Different switching frequency on certain channels) that could not be accomplished with the libraries. This is transparent to the end user.

The library uses a number of of resources on the Freedom board. The list below show what the library uses. The user should not use the MBED libraries to talk to those ports/peripherals.

I/O: -

  • PTB0 (Servo Channel 0 - TPM1)
  • PTB1 (Servo Channel 1 - TPM1)
  • PTB8 (Battery LED0)
  • PTB9 (Battery LED1)
  • PTB10 (Battery LED2)
  • PTB11 (Battery LED3)
  • PTD7 (Camera SI)
  • PTE0 (Camera CLK)
  • PTD5 (Camera A0 - ADC_SE6b)
  • PTD6 (Camera A1 - ADC_SE7b)
  • PTE2 DIP Switch 0
  • PTE3 DIP Switch 1
  • PTE4 DIP Switch 2
  • PTE5 DIP Switch 3
  • PTC13 Pushbutton SW1
  • PTC17 Pushbutton SW2
  • PTC3 H-Bridge A - 1 FTM0_CH3
  • PTC4 H-Bridge A - 2 FTM0_CH4
  • PTC1 H-Bridge B - 1 FTM0_CH1
  • PTC2 H-Bridge B - 2 FTM0_CH2
  • PTE21 H-Bridge Enable
  • PTE20 H-Bridge Fault
  • PTE23 H-Bridge A - IFB
  • PTE22 H-Bridge B - IFB
Committer:
emh203
Date:
Mon Mar 17 14:10:28 2014 +0000
Revision:
5:9fd02d06973b
Parent:
4:8a4a3fc59e57
Last commit had bug in code.  Selecting NumCameras=2 was not functional.   Removed this as not necessary.   Simplified loops to send data over USB interface.     Increased update rate to PC &  verified operation with new .net front end

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emh203 3:23cce037011f 1 #include "mbed.h"
emh203 3:23cce037011f 2 #include "TFC.h"
emh203 3:23cce037011f 3
emh203 3:23cce037011f 4
emh203 3:23cce037011f 5 //This macro is to maintain compatibility with Codewarrior version of the sample. This version uses the MBED libraries for serial port access
emh203 3:23cce037011f 6 Serial PC(USBTX,USBRX);
emh203 3:23cce037011f 7
emh203 3:23cce037011f 8 #define TERMINAL_PRINTF PC.printf
emh203 3:23cce037011f 9
emh203 3:23cce037011f 10
emh203 3:23cce037011f 11 //This ticker code is used to maintain compability with the Codewarrior version of the sample. This code uses an MBED Ticker for background timing.
emh203 3:23cce037011f 12
emh203 3:23cce037011f 13 #define NUM_TFC_TICKERS 4
emh203 3:23cce037011f 14
emh203 3:23cce037011f 15 Ticker TFC_TickerObj;
emh203 3:23cce037011f 16
emh203 3:23cce037011f 17 volatile uint32_t TFC_Ticker[NUM_TFC_TICKERS];
emh203 3:23cce037011f 18
emh203 3:23cce037011f 19 void TFC_TickerUpdate()
emh203 3:23cce037011f 20 {
emh203 3:23cce037011f 21 int i;
emh203 3:23cce037011f 22
emh203 3:23cce037011f 23 for(i=0; i<NUM_TFC_TICKERS; i++)
emh203 3:23cce037011f 24 {
emh203 3:23cce037011f 25 if(TFC_Ticker[i]<0xFFFFFFFF)
emh203 3:23cce037011f 26 {
emh203 3:23cce037011f 27 TFC_Ticker[i]++;
emh203 3:23cce037011f 28 }
emh203 3:23cce037011f 29 }
emh203 3:23cce037011f 30 }
emh203 3:23cce037011f 31
emh203 3:23cce037011f 32
emh203 3:23cce037011f 33
emh203 3:23cce037011f 34
emh203 3:23cce037011f 35 int main()
emh203 3:23cce037011f 36 {
emh203 5:9fd02d06973b 37 uint32_t i,t = 0;
emh203 3:23cce037011f 38
emh203 3:23cce037011f 39 PC.baud(115200);
emh203 3:23cce037011f 40 TFC_TickerObj.attach_us(&TFC_TickerUpdate,2000);
emh203 3:23cce037011f 41
emh203 3:23cce037011f 42 TFC_Init();
emh203 3:23cce037011f 43
emh203 3:23cce037011f 44 for(;;)
emh203 3:23cce037011f 45 {
emh203 3:23cce037011f 46 //TFC_Task must be called in your main loop. This keeps certain processing happy (I.E. Serial port queue check)
emh203 3:23cce037011f 47 // TFC_Task();
emh203 3:23cce037011f 48
emh203 3:23cce037011f 49 //This Demo program will look at the middle 2 switch to select one of 4 demo modes.
emh203 3:23cce037011f 50 //Let's look at the middle 2 switches
emh203 3:23cce037011f 51 switch((TFC_GetDIP_Switch()>>1)&0x03)
emh203 3:23cce037011f 52 {
emh203 3:23cce037011f 53 default:
emh203 3:23cce037011f 54 case 0 :
emh203 3:23cce037011f 55 //Demo mode 0 just tests the switches and LED's
emh203 3:23cce037011f 56 if(TFC_PUSH_BUTTON_0_PRESSED)
emh203 3:23cce037011f 57 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 58 else
emh203 3:23cce037011f 59 TFC_BAT_LED0_OFF;
emh203 3:23cce037011f 60
emh203 3:23cce037011f 61 if(TFC_PUSH_BUTTON_1_PRESSED)
emh203 3:23cce037011f 62 TFC_BAT_LED3_ON;
emh203 3:23cce037011f 63 else
emh203 3:23cce037011f 64 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 65
emh203 3:23cce037011f 66
emh203 3:23cce037011f 67 if(TFC_GetDIP_Switch()&0x01)
emh203 3:23cce037011f 68 TFC_BAT_LED1_ON;
emh203 3:23cce037011f 69 else
emh203 3:23cce037011f 70 TFC_BAT_LED1_OFF;
emh203 3:23cce037011f 71
emh203 3:23cce037011f 72 if(TFC_GetDIP_Switch()&0x08)
emh203 3:23cce037011f 73 TFC_BAT_LED2_ON;
emh203 3:23cce037011f 74 else
emh203 3:23cce037011f 75 TFC_BAT_LED2_OFF;
emh203 3:23cce037011f 76
emh203 3:23cce037011f 77 break;
emh203 3:23cce037011f 78
emh203 3:23cce037011f 79 case 1:
emh203 3:23cce037011f 80
emh203 3:23cce037011f 81 //Demo mode 1 will just move the servos with the on-board potentiometers
emh203 3:23cce037011f 82 if(TFC_Ticker[0]>=20)
emh203 3:23cce037011f 83 {
emh203 3:23cce037011f 84 TFC_Ticker[0] = 0; //reset the Ticker
emh203 3:23cce037011f 85 //Every 20 mSeconds, update the Servos
emh203 3:23cce037011f 86 TFC_SetServo(0,TFC_ReadPot(0));
emh203 3:23cce037011f 87 TFC_SetServo(1,TFC_ReadPot(1));
emh203 3:23cce037011f 88 }
emh203 3:23cce037011f 89 //Let's put a pattern on the LEDs
emh203 3:23cce037011f 90 if(TFC_Ticker[1] >= 125)
emh203 3:23cce037011f 91 {
emh203 3:23cce037011f 92 TFC_Ticker[1] = 0;
emh203 3:23cce037011f 93 t++;
emh203 3:23cce037011f 94 if(t>4)
emh203 3:23cce037011f 95 {
emh203 3:23cce037011f 96 t=0;
emh203 3:23cce037011f 97 }
emh203 3:23cce037011f 98 TFC_SetBatteryLED_Level(t);
emh203 3:23cce037011f 99 }
emh203 3:23cce037011f 100
emh203 3:23cce037011f 101 TFC_SetMotorPWM(0,0); //Make sure motors are off
emh203 3:23cce037011f 102 TFC_HBRIDGE_DISABLE;
emh203 3:23cce037011f 103
emh203 3:23cce037011f 104
emh203 3:23cce037011f 105 break;
emh203 3:23cce037011f 106
emh203 3:23cce037011f 107 case 2 :
emh203 3:23cce037011f 108
emh203 3:23cce037011f 109 //Demo Mode 2 will use the Pots to make the motors move
emh203 3:23cce037011f 110 TFC_HBRIDGE_ENABLE;
emh203 3:23cce037011f 111
emh203 3:23cce037011f 112 TFC_SetMotorPWM(TFC_ReadPot(0),TFC_ReadPot(1));
emh203 3:23cce037011f 113
emh203 3:23cce037011f 114
emh203 3:23cce037011f 115 //Let's put a pattern on the LEDs
emh203 3:23cce037011f 116 if(TFC_Ticker[1] >= 125)
emh203 3:23cce037011f 117 {
emh203 3:23cce037011f 118 TFC_Ticker[1] = 0;
emh203 3:23cce037011f 119 t++;
emh203 3:23cce037011f 120 if(t>4)
emh203 3:23cce037011f 121 {
emh203 3:23cce037011f 122 t=0;
emh203 3:23cce037011f 123 }
emh203 3:23cce037011f 124 TFC_SetBatteryLED_Level(t);
emh203 3:23cce037011f 125 }
emh203 3:23cce037011f 126 break;
emh203 3:23cce037011f 127
emh203 3:23cce037011f 128 case 3 :
emh203 3:23cce037011f 129
redxeth 4:8a4a3fc59e57 130
emh203 3:23cce037011f 131 //Demo Mode 3 will be in Freescale Garage Mode. It will beam data from the Camera to the
emh203 3:23cce037011f 132 //Labview Application
emh203 3:23cce037011f 133
redxeth 4:8a4a3fc59e57 134
emh203 5:9fd02d06973b 135 if(TFC_Ticker[0]>50 && TFC_LineScanImageReady>0)
emh203 3:23cce037011f 136 {
emh203 3:23cce037011f 137 TFC_Ticker[0] = 0;
emh203 3:23cce037011f 138 TFC_LineScanImageReady=0;
emh203 3:23cce037011f 139 TERMINAL_PRINTF("\r\n");
emh203 3:23cce037011f 140 TERMINAL_PRINTF("L:");
emh203 3:23cce037011f 141
emh203 3:23cce037011f 142 if(t==0)
emh203 3:23cce037011f 143 t=4;
emh203 3:23cce037011f 144 else
emh203 3:23cce037011f 145 t--;
emh203 3:23cce037011f 146
emh203 3:23cce037011f 147 TFC_SetBatteryLED_Level(t);
emh203 3:23cce037011f 148
redxeth 4:8a4a3fc59e57 149 // camera 1
emh203 5:9fd02d06973b 150 for(i=0;i<128;i++)
emh203 3:23cce037011f 151 {
emh203 5:9fd02d06973b 152 TERMINAL_PRINTF("%X,",TFC_LineScanImage0[i]);
emh203 3:23cce037011f 153 }
emh203 5:9fd02d06973b 154
emh203 5:9fd02d06973b 155 // camera 2
emh203 5:9fd02d06973b 156 for(i=0;i<128;i++)
emh203 5:9fd02d06973b 157 {
emh203 5:9fd02d06973b 158 if(i==127)
emh203 5:9fd02d06973b 159 TERMINAL_PRINTF("%X\r\n",TFC_LineScanImage1[i]);
emh203 5:9fd02d06973b 160 else
emh203 5:9fd02d06973b 161 TERMINAL_PRINTF("%X,",TFC_LineScanImage1[i]);
emh203 5:9fd02d06973b 162
emh203 5:9fd02d06973b 163 }
emh203 3:23cce037011f 164 }
emh203 5:9fd02d06973b 165
emh203 3:23cce037011f 166 break;
emh203 3:23cce037011f 167 }
emh203 3:23cce037011f 168 }
emh203 3:23cce037011f 169
emh203 3:23cce037011f 170
emh203 3:23cce037011f 171 }
emh203 3:23cce037011f 172