1.    Previous Content

This blog details experimentation and investigation of the Digilent BASYS MX3 board as part of the BASYS MX3 Trainer Board roadtest and I will be writing a roadtest report on this product in the following week based on these more detailed blogs. My previous blog posts on this board are:

 

 

2.    Aims of This Blog #3

For this blog #3 I would like to:

  • Run through the tutorial material on the Seattle University site which covers five separate topics
  • Test out all of the Digilent workshop examples
  • Hopefully to learn the basics of RTOS - I am hoping this will be in those tutorials as this will be the branching away from the non-RTOS designs covered in previous blogs.

 

3.    The Seattle University Training

The online tutorial covers five topics which are:

  • Seven Segment Display: demonstrates how to use freeRTOS tasks, queues and timers to monitor a button on the Basys MX3 and update the built-in seven segment display.
  • Convective Heat Transfer Coefficient: demonstrates how the Basys MX3 might be used to collected temperature data in a heat transfer experiment. The activity also demonstrates how to use an SPI device and how to stream data from the Basys MX3 to a PC.
  • Natural Frequency of a Cantilevered Beam: demonstrates how the Basys MX3 might be used to collect data in a vibration experiment. The activity also demonstrates how to store and retrieve data on the Basys MX3's built-in 4MB flash memory.
  • Position Control of a DC Motor: demonstrates how the Basys MX3 might be used in an experiment to control a servomotor. The activity also demonstrates how to use PWM and hardware interrupts on the PIC32 and how to use the built-in H-Bridge on the Basys MX3.
  • Frequency of an Audio Signal: demonstrates how to use freeRTOS and hardware timers to control sample rate. The activity also demonstrates how to use the PIC32 DSP Library FFT function.

 

Each of these five topics is laid out using the same sequence of sub-tabs, as shown below, and these help keep the reader from getting lost and confused. IMO that is a really good approach.

  • Overview
  • Equipment
  • Code
  • Instructions
  • Lab Project
  • Assignment
  • Demonstration

3.1    Activity 1: Seven Segment Display (SSD)

My first impressions as I read the Overview tab were very good as there are some great explanations of the project requirements such as how to prevent multiplexed display flicker and how often the button should be polled to create a responsive project. I found the Equipment tab to also give some really useful information detailing the basics of multiplexed displays and seven segment display layouts. This tab then starts to show how the LibPack abstracts some operations to a higher level for ease of coding i.e. LED_Toggle(0) to toggle the state of LED number 0. This level of abstraction will appear very familiar to Arduino users.

 

The Code tab lists the main function and it could be tempting to create a new project and paste that code into a newly created main.c. However the user would then need to add all the other linked in libraries and ensure the paths were correct. Luckily I held off and read the Instructions tab. This later tab details downloading the project complete as a zipped package. Downloading and unzipping that allowed MPLAB X IDE to seamlessly pick up the new SSD.X project. The instructions were very complete and I was pleased with the quality. The following is a screenshot of the SSD project as loaded into MPLAB X IDE v5.25 and I have expanded out the folders to show you the types of file they contain. This structure is different to the simple LibPack demonstrations in the previous blog Digilent BASYS MX3: #2 The LibPack Demo Projects and most notably by the inclusion of the RTOS folder and BasysMX3setup.h

I then clicked 'Clean and Build' and 'Make and Program' to complete the project and download it to the BASYS MX3 board....and started to run. The SSD shows '0000', the LCD display is blank and the LED numbered LD0 flashes with 1 second on and 1 second off. Pressing the 'down' button results in the SSD incrementing on the push (rather than release of button).

 

The training material then challenges the reader to modify the code:

This is where the RTOS fun starts and without much explanation. That isn't too much of an issue as the code is well written and easy to read through. Straight away the creation of some entities to represent tasks that are to be undertaken.

 

I started modifying the ssdUpdate function to release each 7-segment element for longer than the recommended 4ms (total 16ms) and at 8ms on each (32ms total) I noticed the display had started to flicker.

// refresh the individual digits and release the task for 4ms
ssdSetDigit(0, digit1);
vTaskDelay(4);

ssdSetDigit(1, digit10);
vTaskDelay(4);

ssdSetDigit(2, digit100);
vTaskDelay(4);

ssdSetDigit(3, digit1000);
vTaskDelay(4);
   

 

Looking at the code it is the trackButton function that increments the counter based on the way the push button operates. That was quite easy to change as the code has been written very neatly. After changing the code as shown below the SSD incremented only when the down button was released. What is interesting as well is because this is running as a RTOS holding the button down does not prevent the LED being blinked at 1s - something that often happens if the code blocks whilst waiting for the button release.

// Modified 14rhb: if there was a change in state of the button (transitioned from down to up)
       
// add one to the counter and update the SSD

if (buttonD == UP && buttonD != prevbuttonD) {
            count++;
            if (count > 9999) count = 0;  // reset the counter
            xQueueSendToBack(SSDqueue, &count, portMAX_DELAY);  // update the SS Display
        }

 

The timer to flash the LED is initially setup as every 1000ms, this value can be easily changed to 300 to make the ticks every 300ms although reducing further to 100ms is much more noticeable and the push button increment functionality still works.

xTimer1000 = xTimerCreate((const signed char *) "Blinky",
100, // The timer period. 1000 ticks = 1 seconds */
pdTRUE, // This is an auto-reload timer, so xAutoReload is set to pdTRUE. 
(void *) 0, // The ID is not used, so can be set to anything. 
Timer1000 // The callback function that inspects the status of all the other tasks.
 );

 

That was a very nice and simple project using RTOS and it showed simply the benefits of such an approach, although the code is more complex and would be larger than a standard non-RTOS design. I don't plan to actually undertake each of the assignments listed as those are learning units and what I really want is to make my own project as part of this roadtest. However what is good is that the last Demonstration tab shows a video of the completed assignment along with their suggested code....for those trainees who get stuck.

 

From this first training activity I am impressed with this Seattle University course and also with the ease of functionality under the RTOS (although it is at first glance quite complex).

 

3.2      Activity 2: Convective Heat Transfer Coefficient

Unfortunately this activity requires the use of the Pmod TC1, which I don't currently have. But looking through the Equipment tab I see mention of using the LibPack SPI functions and wonder if I could modify this to at least read from one of my other Pmod devices. I downloaded the zipped project files anyway for some experimentation. My first task was to build and download just to see if it actually worked without the Pmod unit I have, the CMPS2 compass unit. It is definitely a hot day in the office!

What it is showing me is that I could likely change this code to read my compass unit values. After some more reading I find my Pmod unit is I2C and this activity 2 example uses an SPI based Pmod. There would be a lot of work to change this across and therefore I will be content to just assess the printed material rather than modify the code at this stage.

 

However I am noting this as it might be a good contender to modify for a final project as a CSV file is also generated and it will be interesting to view in Excel or other spreadsheet application.

 

The Activity 2 ends with a Demonstration tab again that shows a video of the final experimentation and example of code that answers the lab questions. This is another well presented example which almost works straight away and which shows how the RTOS is utilised for SPI interaction, LCD displays are written to and how the UART can be used.

 

3.3    Activity 3: Natural Frequency of a Cantilevered Beam

Unfortunately this activity also relies on a sensor that I do not have (the ADXL335), although the aluminium beam I could likely find a substitute for. However I still looked through the code to see what it achieved as I will then be able to re-purpose sections if required for my own projects. I downloaded the VibratingBeam.X.xzip project so I could search and explore the code directly in MPLAB X IDE.

 

The Overview tab explains the basics of this activity; whereby the analog Z-axis signal from an accelerometer IC (attached to a vibrating beam) is fed to the BASYS MX3 Analog-to-Digital converter. This digital representation of the vibration is then processed using a Fast Fourier Transform (FFT) library function to reveal the underlying fundamental frequency. This is really interesting stuff !

[photo source: https://sumechanical.org/asee2018/  ]

 

In a similar way to the preceding two RTOS activities, this activity has tasks created. These are:

  • LCD Update
  • calculate FFT
  • collect Data
  • output Data
  • track the Buttons

 

What I have noticed is that the functions listed in MPLAB X IDE under the RTOS folder are the same for each activity meaning they are a generic pull in to the project rather than needing creating and adding manually...this is good. This activity will be useful for reading values from any analog sensor at a reasonable rate (200Hz in this example) and to display the frequency. For example the microphone could likely be utilised as the source and the underlying main frequency determined. A guitar tuner also springs to mind under the possible uses. The power of FFT being realised due to the main PIC32MX device and larger amounts of RAM and RTOS over the lighter weight 8-bit devices I more often use.

 

I looked forward to the Demonstration tab on this activity to see the video of the project running as intended and I wasn't disappointed.

 

3.4    Activity 4: Position Control of a DC Motor

As I started to look through this activity I realised it was another one that I couldn't complete as it required a DC motor with a rotary encoder. As in previous activities I decided to download and explore the project code and the Seattle University instructions to see what I could learn.

[photo source: https://sumechanical.org/asee2018/Feedback/Media/feedbackequipment.svg  ]

 

This activity makes use of the BASYS MX3's ADC capability and the inbuilt H-bridge DC motor drive. It allows the user to adjust the final position of the motor and the overshoot in this control system.

 

As previously seen several instances of xTaskCreate are called to make tasks that run together on the RTOS system. Each of these tasks can be seen to get a priority number also with the button pushes and LCD remaining lowest whilst the more critical motor positioning is higher priority. These can be seen in the MPLAB X IDE screenshot below (click to zoom):

As I explore the code further it does start to get quite complex, in a similar way to how I found many of the ARM based demo boards which used some form of RTOS. There is a link at the end of this blog on RTOS and I delved into that literature a few times which helped my understanding to some extent.

 

For anyone like me who cannot built this activity the Seattle University website has some fantastic interactive demos under the Assignment tab. These allow the user to adjust the proportional gain and then command the motor to a position, the higher the gain the more overshoot can be seen. If you are interesting in motor operation in general this page itself is a great read regardless of any interest in MCU !

 

3.5    Activity 5: Frequency of an Audio Signal

I downloaded and unzipped the project code for this activity and loaded the project into MPLAB X IDE. The project contains man of the LibPack headers and therefore I know the project will make use of these peripherals. The RTOS folder is also populated and therefore I know this activity will make use of those functions to create a real-time system. However the starting point to investigate is under main.c

 

As a real-time system the code sets up two tasks:

  • analyseAudio
  • ssdUpdate

 

These are the main two functions that are called as the system determines. The analyseAudio collects data points form the microphone, determines which frequency bin has the greatest magnitude and parses that to the SSD for display. The ssdUpdate does exactly that and displays the data to the 7-segment display at a refresh rate to elliminate flicker.

 

There are three schemes to choose from:

1          1000Hz

2          4000Hz

3          16000Hz

 

The latter uses an ISR for the data processing and I believe whilst in there it causes the SSD to fliicker. I switched back to scheme1 for my tests. The Javascript on the Seattle University website allows the user to play test tones that can check the board's operation:

Below is a short video showing the Digilent BASYS MX3 board running the FFT.x demo:

 

Note to myself: this FFT function can be used to make my Christmas LED lights flash directly to music without the need to choreograph them in sequencing software or a guitar tuner

 

3.6    Resources

If you missed my point in earlier blog posts, this Seattle University website contains some great material relating to installing the MPLAB X IDE software and XC32 compiler.

 

 

4.    Digilent Online Training

The online Digilent tutorial covers seven work units, although unit number four is split into two parts. The units are:

 

  • Unit 1: Microprocessor I/O
  • Unit 2: Elements of Real-Time Systems
  • Unit 3: Parallel I/O and Handshaking for LCD Control
  • Unit 4: part 1, communications - Serial Protocol
  • Unit 4: part 2, communications - Asynchronous Serial Protocols
  • Unit 5: IrDA Communications Protocols
  • Unit 6: Analog I/O and Process Control
  • Unit 7: AUdio SIgnal Processing

4.1    Unit 1: Microprocessor I/O

[https://reference.digilentinc.com/learn/courses/microprocessor-io-unit-1/start ]
This first unit contains many hyperlinks in the initial discussions and I'm divided as to whether that is a good thing or might cause a novice to end up reading too much background material. Perhaps a caveat early on to caution the reader against clicking on every single hyperlink unless they really do need to read up on that topic.


This unit is a fairly random collection of articles IMO but there was a lot of really useful fact included and therefore a very good read. It is also very interesting for anyone interested in microcontrollers or software design. I think it is a pity that Digilent don't take the newcomer along the route to use MPLAB X IDE rather than pass them off to the Microchip website as upon clicking that link the user is faced with a completely different layout and interaction, whilst at the same time I can see it would ensure the reader gets to instructions on the latest versions of the IDE rather than perhaps outdated documentation.

 

4.1.1    Appendix A: Starting a New MPLAB X Project

Below is some comments I had from working through this section on making a project from scratch. Bold is my comments or adjustments.

Select Tool: Licensed Debugger MCU Alpha One

Click on “Windows” → “PIC Memory Views”"Target Memory Views" → “Configuration Bits”.

Set the options as shown in Listing B.1 in the Appendix. This part seems quite complex for a newcomer although it does show how the configuration bits can be selected via the drop down tool rather than having to be looked up in the data sheets.

Click on “Generate Source Code to Output” at the bottom of the screen.

// PIC32MX370F512L Configuration Bit Settings
// 'C' source line config statements
// DEVCFG3
#pragma config USERID = 0xFFFF          // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config FSRSSEL = PRIORITY_7     // Shadow Register Set Priority Select (SRS Priority 7)
#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
// DEVCFG2
#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (20x Multiplier)
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider (PLL Divide by 1)
// DEVCFG1
#pragma config FNOSC = PRIPLL           // Oscillator Selection Bits (Primary Osc w/PLL (XT+,HS+,EC+PLL))
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF               // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = HS             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_8           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)
// DEVCFG0
#pragma config DEBUG = OFF              // Background Debugger Enable (Debugger is Disabled)
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx1        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>

 

Once a config_bits.h file is generated, it can be copied to other projects without needing to complete steps a through j. That's nice to know.

Right-click on Source Files and select “New” → “C Main File..”. Name this file “main.” and the extension set to “c”, so it will be “main.c”. It is under New/Other

Add a main function code as shown in Listing A.1. The return denotes an EXIT FAILURE because embedded systems code should never exit from the function main because it inherently has no place to return to. A useful piece of information.

4.1.2    Appendix B

This contains the Configuration Settings for a typical PIC32MX370F512L device

4.1.3    Appendix C

This details two files called header.c and header.h that include some simple macro definitions and functions that the user will likely require often. Including them in a new project is recommended.

4.1.4    Appendix D

This gives a good overview of the PIC32 microcontroller's I/O port operation, including the LATx, TRISx and PORTx commands.

4.1.5    Appendix E

This lists all of the PIC32MX370F512L pin functions. This is always useful as it reminds the user there is an actual device at the centre of this board. Also as many pins have multiple functions the importance of configuration pins and registers can start to be appreciated.

4.1.6    Lab 1a

"In this lab, you will turn the RED, BLUE, and GREEN colours of the tri-colour LED8 either on or off using SW0, SW1, and SW2, respectively."
And below is the code I made, which after a few corrections started to work as expected...my first PIC32MX code
// Lab 1a for Element14 Community Digilent BASYS MX3 Roadtest
// by 14rhb

int main(int argc, char** argv)
{
    // Initialization code goes here
    //Set the PORT D TRIS register to set the bits for LED8_R, LED8_G, and LED8_R as digital outputs.
    TRISDbits.TRISD3  = 0;  // Set Port D3, blue LED as output
    ANSELDbits.ANSD3  = 0;    // Disable analog input
    TRISDbits.TRISD12 = 0;  // Set Port D12, green LED as output
    //ANSELDbits.ANS12 = 0;    // D12 does not have analog selection
    TRISDbits.TRISD2 = 0;  //  Set Port D3, red LED as output
    ANSELDbits.ANSD2 = 0;    // Disable analog input
    //Set the PORT F TRIS register to set the bits SW0 through SW2 as digital inputs. red=sw0, green = sw1 and blue=sw2
    //Port F doesn't seem to have analog signals and therefore no ANSELFbits, source Table 12-11 in datasheet.
    TRISFbits.TRISF3  = 1;  // Set Port RF3, Sw0 = red as input
    //ANSELFbits.ANSF3  = 0;    // Disable analog input
    TRISFbits.TRISF5 = 1;  // Set Port RF5, sw1 = green as input
    //ANSELFbits.ANSF5 = 0;    // D12 does not have analog selection
    TRISFbits.TRISF4 = 1;  //  Set Port RF4, sw2=blue as input
    //ANSELFbits.ANSF4 = 0;    // Disable analog input
    LATDbits.LATD2=0;
    LATDbits.LATD12=0;
    LATDbits.LATD3=0;
    while(1)
      {
        // User code in infinite loop
        LATDbits.LATD2=PORTFbits.RF3;
        LATDbits.LATD12=PORTFbits.RF5;
        LATDbits.LATD3=PORTFbits.RF4;
      }
    return (EXIT_FAILURE);  // Failure if code executes
                            // this line of code.
} // End of main.c

 

In future projects I need to include the hardware.h or macros to abstract away from the use of ports and bit numbers as that can become tedious and error prone.

 

4.1.7    Lab 1b

"The objective of this lab is to program the PIC32 processor to implement the functionality of a simple integer calculator that displays the result of X • Y where the operator, •, will be add, subtract, multiply, or divide. The most recently computed result is continuously displayed on the 7-segment LEDs such that if an operation push button is held depressed and the X or Y switches change position, the new value is immediately seen on the LED display."
This unit's lab 1b experiment expects the user to use the slide switches to present two 4-bit values. A mathematical operation is then performed on them according to which push button is pressed:
  • Down      Add
  • Centre    Subtract
  • Right      Multiply
  • Up          Divide
  • Left          Clear
I'm not sure if I really achieved this as the Digilent task implied but it does undertake the mathematical operations correctly and holding the function buttons allows a real-time change of the X and Y values. Incidentally those are Y is left four switches and X is right four switches; in hindsight I should have swapped them around. I also added an LCD function as a welcome message. The only issue was that the LED display flicked occasionally during the operation and I am unsure why.
/*
* File:  main.c
* Author: 14rhb
*
* Created on 25 October 2019, 16:16
*/
#include <stdio.h>
#include <stdlib.h>
#include "config_bits.h"
//#include "hardware.h"
#include "../BASYS_MX3_Lib/Basys-MX3-library-master/LibPack/LibPack.X/ssd.h"
#include "../BASYS_MX3_Lib/Basys-MX3-library-master/LibPack/LibPack.X/lcd.h"
#include "strings.h"
#include "../BASYS_MX3_Lib/Basys-MX3-library-master/LibPack/LibPack.X/utils.h"
int testPushbuttons(int);
void displayAnswer(unsigned int );
void calculateAnswer(int, int, int );
int main(int argc, char** argv)
{
    unsigned int x=0;
    unsigned int y=0;
    int operation=0;
    unsigned int answer=0;
    SSD_Init();
    //Pushbutton Setup
    TRISBbits.TRISB1 = 1; // RB1 (BTNU) configured as input
    ANSELBbits.ANSB1 = 0; // RB1 (BTNU) disabled analog
    TRISBbits.TRISB0 = 1; // RB1 (BTNL) configured as input
    ANSELBbits.ANSB0 = 0; // RB1 (BTNL) disabled analog
    TRISFbits.TRISF4 = 1; // RF0 (BTNC) configured as input
    TRISBbits.TRISB8 = 1; // RB8 (BTNR) configured as input
    ANSELBbits.ANSB8 = 0;// RB8 (BTNR) disabled analog
    TRISAbits.TRISA15 = 1;// RA15 (BTND) configured as input
    //Set the 7-segment display up - luckily this is in section 7.1 of the BASYS MX3 user guide
    TRISBbits.TRISB12 = 0; //RB12 set as output
    ANSELBbits.ANSB12 = 0; //RB12 analog functionality disabled
    TRISBbits.TRISB13 = 0; //RB13 set as output
    ANSELBbits.ANSB13 = 0; //RB13 analog functionality disabled
    TRISAbits.TRISA9 = 0; //RA9 set as output
    TRISAbits.TRISA10 = 0; //RA10 set as output
    TRISGbits.TRISG12 = 0; //RG12 set as output
    TRISAbits.TRISA14 = 0; //RA14 set as output
    TRISDbits.TRISD6 = 0; //RD6 set as output
    TRISGbits.TRISG13 = 0; //RG13 set as output
    TRISGbits.TRISG15 = 0; //RG15 set as output
    TRISDbits.TRISD7 = 0; //RD7 set as output
    TRISDbits.TRISD13 = 0; //RD13 set as output
    TRISGbits.TRISG14 = 0; //RG14 set as output
    //Set the registers for slide switches
    TRISFbits.TRISF3  = 1;  // Set Port Sw0 as input
    TRISFbits.TRISF5 = 1;  // Set Port SW1 as input
    TRISFbits.TRISF4 = 1;  //  Set Port SW2 as input
    TRISDbits.TRISD15 = 1; //  Set SW3 as input
    TRISDbits.TRISD14 = 1; //  Set SW4 as input
    TRISBbits.TRISB11 = 1; //  Set SW5 as input
    ANSELBbits.ANSB11 = 0;
    TRISBbits.TRISB10 = 1; //  Set SW6 as input
    ANSELBbits.ANSB10 = 0;
    TRISBbits.TRISB9 = 1; //  Set SW7 as input
    ANSELBbits.ANSB9 = 0;
    LCD_Init();
    char message[]="Hello, welcome to the Element14 Community Roadtest of the Digilent BASYS MX3 Board...lab 1b demo                " ;
    char snippet[16];
    int i=0;
    for (; i<90; i++){
        memset (snippet, "\0", sizeof(snippet));
        strncpy(snippet,message+i, 16);
        LCD_WriteStringAtPos(snippet, 0, 0);
        int delay=0;
        for(; delay<250000; delay++){
            DelayAprox10Us;            //100* = 1ms,  100,000 = 1s
        }
    }
    LCD_WriteStringAtPos("  E14 - Lab 1b  ", 0, 0);
    // User code in infinite loop
    while(1)
      {
        operation = testPushbuttons(operation);
      }
    return (EXIT_FAILURE);  // Failure if code executes
                            // this line of code.
} // End of main.c
/*    returns value if button pressed
      1= up
      2=down
      3=right
      4=left
      5=centre
  */
int testPushbuttons(int currentValue){
    int value=currentValue;
    int x,y;
    if (PORTBbits.RB1==1) value=1;
    if (PORTBbits.RB0==1) value=4;
    if (PORTAbits.RA15==1) value=2;
    if (PORTBbits.RB8==1) value=3;
    if (PORTFbits.RF0==1) value=5;
    //this is effectively where keys are held - wait for key to be released
    while(PORTBbits.RB1!=0 || PORTBbits.RB0!=0 || PORTAbits.RA15!=0 || PORTBbits.RB8!=0 || PORTFbits.RF0!=0){
        x=readSlideSwitchesX();
        y=readSlideSwitchesY();
        calculateAnswer(value,x,y);
    };
    LCD_WriteStringAtPos("                ", 1, 0);
    return value;
}
int readSlideSwitchesX(){
    //value for x read
    int x=0;
    if(PORTFbits.RF3==1)x++;
    if(PORTFbits.RF5==1)x+=2;
    if(PORTFbits.RF4==1)x+=4;
    if(PORTDbits.RD15==1)x+=8;
    return x;
}
int readSlideSwitchesY(){
    //value for y read
    int y=0;
    if(PORTDbits.RD14==1)y++;
    if(PORTBbits.RB11==1)y+=2;
    if(PORTBbits.RB10==1)y+=4;
    if(PORTBbits.RB9==1)y+=8;
    return y;
}
void calculateAnswer(int operation, int x, int y){
    int answer;
    if (operation==1){  //divide
        LCD_WriteStringAtPos("Divide          ", 1, 0);
        answer=(unsigned int)((float)x/(float)y);
    }
    else if (operation==2){    //add
        LCD_WriteStringAtPos("Add            ", 1, 0);
        answer=x+y;
    }
    else if (operation==3){    //multiply
        LCD_WriteStringAtPos("Multiply        ", 1, 0);
        answer=x*y;
    }
    else if (operation==4){    //clear
        LCD_WriteStringAtPos("Clear          ", 1, 0);
        answer=0;
    }
    else if (operation==5){    //subtract
        LCD_WriteStringAtPos("Subtract        ", 1, 0);
        answer=x-y;
    }
    displayAnswer(answer);
}
  void displayAnswer(unsigned int valIn){
    SSD_WriteDigits(valIn & 0xF, (valIn & 0xF0) >> 4, (valIn & 0xF00) >> 8, (valIn & 0xF000) >> 12,0,0,0,0);
    return;
}

At this point I'm going to conclude that I don't want to spend hours implementing each example in these units, struggling to get the code working as intended, which is almost akin to undertaking a formal qualification. Instead I want to read through, see what each unit is offering and perhaps only undertake the assignments that will help my final project idea. That's the plan, so if the following units seem brief I have adopted that approach. I'm still keen to pay more attention to how the RTOS projects are created.

 

4.2    Unit 2: Elements of Real-Time Systems

This unit looks at real-time systems rather than the combinatorial circuits in unit 1a. There are two lab units to work through, 2a and 2b, which require the use of a stepper motor. The concepts of real-time multi-threaded systems are explained well where it appears that such a system is simultaneously servicing multiple tasks in the code. The following concepts are also discussed:
  • Hard Real-time Systems: require all deadlines to be met
  • Firm Real-time Systems: allow for infrequently missing deadlines
  • Soft Real-time Systems: allow for more deadlines to be missed at the detriment of the system performance
Methods of task switching in real-time systems (the easiest two):
  • Cooperative - each task willingly stops to allow others to startup, needs all tasks to work together well
  • Preemptive - this is more from an administrator stopping tasks to run up others
In reality real-time systems use a combination of the above two methods of switching to achieve the best performance and responsiveness. The approach is now called foreground-background scheduling and tasks are given a priority by the system designer.

"The PIC32MX370 has up to 76 different interrupt sources and 46 interrupt vectors."

There are three main types of interrupt:

  • Software
  • Internal hardware
  • External hardware

 

When the Interrupt Service Routine (ISR) is invoked the microcontroller needs to save the context of major registers and settings at that instance of time, it then undertakes the ISR routine before reinstating the context of major registers and settings - this is called prologue and epilogue code.This takes time (which contributes to ISR latency) to undertake which effectively is deadtime to the system. In the PIC32 microcontrollers there are shadow registers of all the major registers and this saving/reinstating of context is almost instantaneous.

 

Preemptive systems generally have foreground and background tasks. There are two types of operating scheme under preemptive: nested and non-nested with nested generally being more responsive. Each can also be used with polling techniques. The PIC32MX range can use polling, nested and non-nested simultaneously. The PIC32MX also uses something called Group Priority (levels 1-7 with one equal to the lowest) and Sub-Group Priority (levels 1-4). This hopefully will become clearer as I start to use it. The Digilent documentation could, IMO, benefit from some simple diagram rather than lots of text.

 

The four code elements required to successful process interrupts are:

  • function declarations for the ISR
  • code to initialise the hardware that generates these interrupts
  • ISR code that will be executed
  • instructions to enable global interrupts

An important point is that the code developer must clear the interrupts to allow the system to be prepared for the next, failure to do this results in the system entering the same ISR again and again and will lock the system up.

 

ISR functions cannot be called from the other code areas in the same way as standard functions and they also cannot accept any variables to be passed to them or from them. They can however call standard functions from their own code.

 

Critical sections of code where it would be detrimental to run any other ISR can be ring-fenced using the instructions INTEnalbeInterrupts() and INTDisableInterrupts().

 

There is a good section on the use of timers and counters in real-time systems and how hardware implementation is better than software implementation.

 

I actually started to get overwhelmed with the content in this section and will need to re-read several sections. There were code snippets and I was unsure if I should start trying to make them into a project. At that point I started to skim through until I found listing A.3 as a complete program. I copied that into my main.c and compiled it.

// E14 Community 1s BLINK Test
// 14rhb
int main(void)
{
   TRISACLR = 0x01;                /* Set LED0 for output */
   LATACLR = 0x01;                 /* Initialize LED for off */

/* Configure Timer1 to roll over once each second */
   OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_8, T1_TICK - 1);

   int val=0;
   
   while (1) 
   {
       if(INTGetFlag( INT_T1 ))
       {
           /* Tasks to be executed each millisecond */
           val++;
           INTClearFlag( INT_T1 );     /* Clear the interrupt flag */
       }
       /* Tasks to be executed at the loop execution rate */
       
       if (val>1000){
            LATAINV = 0x01;             /* Invert LED 0 */
            val=0;
       }     
   } 
   
   return (EXIT_FAILURE);  /* System has failed if this line is reached */
} /* End of File main.c */ 

 

It took me a little while to understand what to do with this as the LED0 appeared to be on constant. Then I modified the code to that shown above such that the ISR is 'ticking' away every 1ms and incrementing val. When val>1000 i.e. 1s the LED0 toggles. What is important here is that for most of those 1ms periods are have control of the MCU and can write other functions, only when the interrupt flag is raised does the code have to run the val++.

 

The unit concludes with two lab assignments:

Lab 2a

Write the code that converts the three momentary contact pushbuttons to operate as push-on/push-off buttons and that satisfies the following specifications:

  1. The state of the three push buttons BTNR, BTNC, and BTND are displayed on LED0 through LED2.

  2. The function provides for a 20 ms debounce period for every press and release of a push button.

  3. The new button state is reported at the start of the 20 ms debounce period.

  4. The button polling function is to be non-blocking during the 20 ms debounce period.

 

Lab 2b

Use the eight slide switches to set the speed of rotation of the stepper motor shaft from 0 to 31.875 RPM in steps of 0.125 RPM. BTND will switch the motor operation from FULL step to HALF step when depressed. BTNR will switch the rotational direction of the rotor from CW to CCW when pressed. The speed of rotation will be displayed on the four-digit seven-segment display digits with 25% duty cycle persistence and one ms update rate.

 

I have opted not to undertake either of those at this point although I note that they are both very detailed in their guidance through the task. Perhaps I will select one of these for my final project.

 

4.3    Unit 3: Parallel I/O and Handshaking for LCD Control

Although I already jumped straight in to use the LibPack LCD.h on previous work this unit is detailing how the PIC32MX can be interfaced to other LCD units - this is invaluable when perhaps breaking away from the development board onto a bespoke product PCB and a different LCD module. The units starts off describing the following concepts:
  • Parallel Communication
  • Serial Communication
  • Handshaking
There is then a nicely detailed section on handshaking and IMO well worth reading regardless of whether you want to use the BASYS MX3 board or just implement this in other ways.
The next section details the LCD interface pins and shows timing diagrams of how the various control lines are pulled high/low and strobed while the data is exchanged. Anyone who has written their own LCD module code in the past will likely be familiar with these diagrams and timing constraints surrounding them.
The unit then moves on to software with a Finite State Machine (FSR) diagram and flow diagrams to show initialisation. This is probably one of the best descriptions I have ever read about LCD setup. I know from experience that the datasheets on the cheaper modules are often lacking in detail.
The unit finally describes two methods for transferring data to an LCD module:
  • Bit-banging
  • Parallel Master Port (PMP)
Code snippets are given for both methods to assist the reader. This unit supplies some interesting appendix information on graphical display usage and custom characters.

The unit concludes with two lab assignments which are:

Lab 3a

"Develop and test a collection functions that allow text to be placed at any position on a parallel I/O character LCD following the DFD and CFD models presented in Unit 3. The LCD_puts function is required to process the ASCII control characters, which are described in Table 8.1."

Lab 3b

"Develop and test a collection of functions that allow text to be placed at any position on a parallel I/O character LCD following the DFD and CFD models presented in Unit 3. The LCD_puts function is required to process the ASCII control characters, which are described in Table 8.1.". This is aimed at the PMP interface although the requirement is stated as being the same as assignment 3a.

4.4    Unit 4: Communications, part 1:Serial Protocol & part 2:Asynchronous Serial Protocols

This double unit gives a really good overview of the OSI communications model and explanations of Asynchronous and Synchronous communications. There is little code or reference to the BASYS MX3 unit in this general module but that detail is left to the later four lab assignments.

 

Appendix B in this unit is great as it lists the popular serial protocols and provides links to the Wikipedia articles on them.

 

The four lab assignments in this unit are:

Lab 4a

"Text messages will be sent to the UART serial port whenever a change in switch settings is detected and the action will be reported to a computer terminal. Whenever a text string is entered on the computer terminal, it will be displayed on the Basys MX3 LCD."

 

Lab 4b

"It requires all of the elements of software code developed and hardware used in previous labs, as well as additional hardware and software to support the serial communications with the PC. This project will require you to input text data from the serial port that will set the direction, mode, and speed of the stepper motor. This interface will be in addition to all of the controls provided in Lab 2b. The text from the serial port will be echoed to the LCD. It will be good for you to review the documentation on how the following text manipulating functions are implemented: printf, sprintf, scanf, and strcmp."

 

Lab 4c

"You are to develop a software system that allows the PIC32MX370 to write an arbitrary number of 8-bit bytes to an arbitrary address location in the SPI flash memory device. You must be able to read back this stored data and determine if the data read matches the data written."

 

Lab 4d

"The PIC32MX370 processor will periodically read the physical orientation data from a 3-Axis accelerometer and display the information on a character LCD and send a text stream to a computer terminal."

 

Each of these above units includes a huge wealth of knowledge and explanation on each of these topics before guiding the reader through development of their solution with code snippets, flow diagrams, more explanations and circuit diagrams. This really is a comprehensive and well laid out set of training material, my few words does little to convey the detail without copying it to this blog verbatim.

 

4.5    Unit 5: IrDA Communications Protocols

This unit is a complete learning module on IrDA and includes the basic overview, the physical layer detail (the Digilent BASYS MX3 comes with its own built in IrDA module) and full discussion on the protocol. This is further reinforced for anyone just reading through the article as it includes many useful logic analyser screenshots of the protocol in action.

 

The unit the goes on to explain the basics of how the PIC32MX370 would encode and decode such a signal, building on the previous units.

 

The unit culminates in a single lab assignment.

 

Lab 5a

"This lab requires the student to analyse the IrDA signal from an arbitrary device remote control unit and generate an application that can exchange IrDA messages with that device."

 

4.6    Unit 6: Analog I/O and Process Control

This unit discusses electro-mechanical systems in a very detailed and methodical way and covers the architectures, mechanisms and algorithms involved. Below is the control block diagram from this Digilent material:

The unit explains the differences between:

  • Open-loop Control
  • Closed-loop Control

 

The next section of the unit explains the basics of Signal Processing including:

  • Analog Signal Processing
  • Digital Signal Processing

 

There is a very detailed section on motor speed control and feedback (which includes the tachometer in the diagram above).

 

The unit concludes with some really succinct motor control information in the appendices before finishing with two user assignments.

 

Lab 6a

"As illustrated in Fig. 5.1, open-loop control does not use feedback to the control processing that indicates how the output is actually working. The open-loop portion of this lab will use the potentiometer labelled Analog Control Input identified as R134 on the Basys MX3 schematic, as shown in Fig. 7.1. It will be used to set the percent PWM to operate the speed of the motor from 0 rpm to the maximum the motor can achieve given the motor performance and the supply voltage. Monitoring of specific signals will validate the control of the PWM output by the Analog Input Control potentiometer using the Analog Discovery 2 and a digital multimeter."

 

Lab 6b

"As illustrated in Fig. 5.1, closed-loop control incorporates a feedback signal along with the analog and discrete inputs to the control process. The tachometer frequency will be measured by using the Input Capture of the PIC32 to determine the signal period which is then inverted to yield the frequency. The tachometer period measurements are filtered with a moving averaging low pass digital filter as described in Lab 6a.

This lab is to use a digital implementation of proportional plus integral (PI) control in the control loop. The speed of the motor will be linearly dependent on the voltage controlled by the Analog Input Control potentiometer. This is described by Eq. 6.1 which results in linear motor speed control that will vary between 30% and 90% of maximum motor speed.

 

MotorSpeed=[(AnalogControlVoltage0.6MaximumAnalogControlVoltage)+0.3]Maximummotorspeed(Eq.6.1)

 

The range of 30% to 90% is selected on the characteristics of the DC motor we are using for Lab 6a and 6b. By experimentation, it was determined that when the motor supply is set to 5.0 V, the %PWM must be set above 25% to 28% or the motor will not turn as shown in Fig. 8.3 of Lab 6a. If the motor is not turning, then there are no input capture interrupts to set the RPS variable in the control algorithm."

 

This looks to be another great and detailed learning unit, the wealth of information in it cannot be conveyed here and I really suggest anyone interested in driving motors from a microcontroller have a read.

4.7    Unit 7: Audio Signal Processing

I was not disappointed as I read through this final unit. The ability to undertake digital signal processing of audio signals is a very powerful and widely used technique - the fact it can be undertaken on this PIC32MX device shows how much processing power is available. The unit starts with a basic chapter on signal processing and links off to several Wikipedia articles. There are then two small sections on audio processing:
  • Analog Signal Processing
  • Digital Signal Processing
A simple block diagram overview from this Digilent material is shown below:

There is a nicely detailed introduction to digital filters, Finite Impulse Response (FIR) filters and Infinite Impulse Response (IIR) filters. The Digilent Unit 7 is a great starting point IMO for any Audio DSP work, whether using the BASYS MX3 or another similar microcontroller board. The units appendices include some useful links to the BASYS MX3 schematics as well as code snippets for several FIR and IIR filters.

 

The unit concludes again with two assignments:

Lab 7a

"You are to create a digital sine wave generator capable of synthesizing eight constant amplitude signals at frequencies specified in Section 8.1. The frequency of the sine waves will be selected by setting one of the eight slide switches. The audible output will be enabled and the frequency displayed on the 4-digit 7-segment display for five seconds when BTND is pressed. The LCD will display the frequency of the selected sine wave."

Lab 7b

"The objective for this lab is to create a graphical spectrum analyzer as modeled in Fig. 8.1. Figure 8.2 shows the LCD and 7-segment display for the result outputs. Figure 8.3 through 8.5 provide an approach to the software organization for this lab. Figure 8.4 shows the tasks to be completed for the system initialisation."

 

5.    Summaries

5.1    Seattle University Material

Having some prebuilt and downloadable project examples as in the Seattle University learning material was an interesting way to quickly see what the RTOS type of projects had to offer and what this board was capable of, whilst at the same time getting thrown straight into something fun and interesting. However it did make me wonder how I would actually create my own project from scratch - I know copying MPLAB X IDE projects to make another project is often not the best approach. What I decided to do was to print out the basic structures used in these examples and therefore hope this will allow me to create my own projects from scratch with minimal effort. Additionally there is the MPLAB Harmony aimed at PIC32 devices and this too might create the basic framework of a project. I will explore that in my projects in later blogs.
Although I didn't have many of the parts required to complete the activities I found them very well presented and laid out. The final tabs showed the expected solution code to any assignments along with a video of how the activity should have worked - this was great for anyone like me not being able to complete the activity. I also liked the way I was "thrown into the deep end" of RTOS but could also just browse the finished code and make a few tweaks. To me this was rewarding as I was starting out with a working product rather than spend hours typing and following instructions just to end with a series of compiler errors and lots of debugging....at the start of learning this can be make-or-break.

5.2     Digilent Training Material

The Digilent units were also very informative but had less 'hand holding' as there was less finished code but rather just snippets to cut and paste or video to watch; this might actually be a better approach for anyone wishing to learn. Sometimes it is just too easy to copy and paste the finished example, run it and then think you can create a similar project from scratch. There were a lot of code sections that I was unsure about and how they could be placed directly into my project. In time I think these will migrate out to headers and source that I pull in directly. Another point I stumbled on was the adding of library functions, in the end I had to add the absolute path in my code as well as a copy of the headers and source into the project...this needs some more though and looking at by me to better understand it.
In summary another great set of very detailed tutorials. There is a huge wealth of information on each topic and they should be a really informative read for anyone wishing to know about these subjects regardless of what their target board is. I strongly recommend people have a look through this Digilent training material.

5.3   PIC32MX Libraries and plib.h

I ran into other issues with the Digilent code where examples had lines such as:

#include <plib.h> /* Include peripheral library */

#include "hardware.h" /* Includes GetPeripheralClock() */

The plib.h was flagged as not being required and hardware.h also caused issues.

 

"Starting with XC32 V1.40, PIC32MX peripheral support libraries are no longer installed as part of the compiler’s installation. These libraries are now installed as a second setup, after the installation of XC32 compiler.

Peripheral libraries for PIC32MX products are not needed for Harmony development. Microchip recommends using MPLAB Harmony for new projects. To download MPLAB Harmony, click here."

 

I'm using XC32 v2.30 so the peripheral support libraries were not installed at the same time and I need to complete the second step. I have not developed using Harmony at the moment and therefore downloaded the PIC32 Legacy Peripheral Libraries zip file, which extracts to an exe.

 

5.4     Reflection on My Aims

I believe I've accomplished all of my aims I had set for blog #3:

  • Run through the tutorial material on the Seattle University site which covers five separate topics
  • Test out all of the Digilent workshop examples
  • Hopefully to learn the basics of RTOS - I am hoping this will be in those tutorials as this will be the branching away from the non-RTOS designs covered in previous blogs

 

To me this section of my roadtest has been far more than just covering the examples. It has been a great opportunity to read about the real-time operating systems and other complexities of the PIC32MX370 devices - effectively this has been a microcontroller version of the Path II Programmable for me . The practical application of this technology into everyday examples is also a great way of learning and being able to accomplish something more advanced. Although I have skipped over much of the material from both suppliers I now know where this all sites and the detail included.
I believe I have only just started out with this board and understanding what it can achieve. If I look at the MPLAB X IDE dashboard I see that the FFT example only uses 18% of the onboard RAM and a measly 7% of the available program space.

6.    What Next ?

I still want to finish off with my own project before writing up my formal roadtest report on this Digilent BASYS MX3. Although this development board is too large for my project I believe it will form a good basis for developing the code prior to making my own PCB and miniaturising the project. I want to use the Pmod unit I bought as part of my Energy Harvesting Design Challenge to re-work an old project that didn't get very far; my Macrobinocular Mk7150 as used in the Starwars film by Luke Skywalker.
My current plan is to read through this material in much more detail over the coming winter months and to be able to learn and experiment further with this Digilent BASYS MX3 board.

7.     Analog Discovery 2

On reflection I incorrectly referred to diagrams in the Digilent training material as a logic analyser, well it kind of was plus so much more, but they were actually screen shots from their very own low-cost solution called Digilent Analog Discovery 2 (which was developed in partnership with National Instruments their parent company). And as I wrote this I recalled there had been a roadtest of it on Element14 community some months ago: Analog Discovery 2 + LabView Home Bundle Digilent, a National Instruments Company
The Analog Discovery 2 unit is available Product LinkProduct Link or in other larger/smaller bundles.
My final roadtest review can be seen here BASYS MX3 Trainer Board - Review