XC8 code for the obstacle avoiding robot
The code for the robot is written using MPLAB Xpress IDE and XC8 compiler, with the PIC16F18855 being configured using Microchip Code Configurator. Then, the main code relies on functions generated by MCC.
The following configuration settings were done using Microchip Code Configurator:
- Clock source HFINTOSC, clock frequency 4MHz, clock divider set to 1. This leads to a main clock frequency of 4MHZ.
- Timer4 is used for PWM6, Timer6 is used for PWM7. Note that these two timers are identical, so we make the same settings for both timers
- Timer settings:
- Clock source FOSC/4
- Prescaler 1:1
- Postscaler 1:1
- Period 1:250 us
- Ext reset source T4CKIPPS pin
- PWM settings
- PWM duty 0%
- PWM polarity: active high
- PWM resolution is 9 bits given the current main clock / timer settings
- A/D convertor is set to operate in basic mode
- Clock source is FRC
- Alignment right
- Positive reference Vdd
- Negative reference Vss
- “Enable continuous operation” is unchecked
- In pin module
- PIN RB0 is set as ANx (analog input)
- Pins RC5 and RC7 are set as outputs (they will control the direction of the motors)
- Pins RC2 and RC4 are set as PWM
Below there are some screen captures from MCC:
Please observe that PWM resolution is 9 bits, so valid settings for the duty cycle are between 0x00 and 0x01FF.
The code
Main code is as follows:
/** Generated Main Source File Company: Microchip Technology Inc. File Name: main.c Summary: This is the main file generated using MPLAB(c) Code Configurator Description: This header file provides implementations for driver APIs for all modules selected in the GUI. Generation Information : Product Revision : MPLAB(c) Code Configurator - 3.15.0 Device : PIC16F18855 Driver Version : 2.00 The generated drivers are tested against the following: Compiler : XC8 1.35 MPLAB : MPLAB X 3.20 */ /* (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this software and any derivatives exclusively with Microchip products. THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS. */ #include "mcc_generated_files/mcc.h" /* Main application */ uint16_t distance; uint16_t too_close = 350; void main(void) { // initialize the device SYSTEM_Initialize(); // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits // Use the following macros to: // Enable the Global Interrupts //INTERRUPT_GlobalInterruptEnable(); // Enable the Peripheral Interrupts //INTERRUPT_PeripheralInterruptEnable(); // Disable the Global Interrupts //INTERRUPT_GlobalInterruptDisable(); // Disable the Peripheral Interrupts //INTERRUPT_PeripheralInterruptDisable(); // Set direction to forward PIN_MANAGER_Initialize (); IO_RC5_SetHigh(); IO_RC7_SetHigh(); // Initialize ADC, conversion by request ADCC_Initialize(); ADCC_DisableContinuousConversion(); // Initialize PWMs and set them to 0 PWM6_Initialize(); PWM6_LoadDutyValue(0x00); PWM6_Initialize(); PWM6_LoadDutyValue(0x00); // Start forward // PWM is 9 bits resolution PWM6_LoadDutyValue(0x01FF); PWM7_LoadDutyValue(0x01FF); while (1) { // Add your application code // Read ADC value, RB0 is channel ANB0 distance = ADCC_GetSingleConversion(channel_ANB0); if ( distance > too_close ){ // stop PWM6_LoadDutyValue(0x00); PWM7_LoadDutyValue(0x00); // wait a bit __delay_ms(500); // turn back IO_RC5_SetLow(); IO_RC7_SetLow(); PWM6_LoadDutyValue(0x01FF); PWM7_LoadDutyValue(0x01FF); // run backwards fro some time __delay_ms(5000); // stop PWM6_LoadDutyValue(0x00); PWM7_LoadDutyValue(0x00); // wait a bit __delay_ms(500); // Turn slowly IO_RC5_SetHigh(); IO_RC7_SetLow(); PWM6_LoadDutyValue(0x00FF); PWM7_LoadDutyValue(0x00FF); // The delay controls how much we turn __delay_ms(2000); // stop PWM6_LoadDutyValue(0x00); PWM7_LoadDutyValue(0x00); // wait a bit __delay_ms(500); // resume going forward IO_RC5_SetHigh(); IO_RC7_SetHigh(); PWM6_LoadDutyValue(0x01FF); PWM7_LoadDutyValue(0x01FF); } } } /** End of File */
Note: if the robot first moves backwards you just have to reverse the output pins on the DRV8835.
As usual, the complete MPLABX package can be downloaded here.
And.. action!