Posted on by

Embedded Programming

Wrapping up the BLUEtongue 2.0 Rover’s Drive System series, following articles by Chris about the mechanical re-design of the system and Harry about the high-level software implementation, this article will outline the role of the embedded system in connecting the electrical motors to the high-level software. Primarily, this article will focus on analog-to-digital converters and their use in the drive system of BLUEtongue 2.0. Some understanding of electrical circuits and microprocessors is assumed in the following explanations.

ADC methodologies

Analog-to-Digital Converters (ADCs) are a cornerstone of signal processing, and are used in nearly all electrical devices today. The objective of an ADC is to convert an analog voltage signal into a digital representation. Various methods exist in implementing an ADC, each having their own benefits and purpose. To provide a comparison there are two key concepts when analysing ADC methods, that being their speed and their cost.

The speed of an ADC reflects how fast a sample-conversion sequence is performed and is most often measured as ‘how many sample-conversions can be done within a certain time-frame’ (in samples per second). A higher speed is of course useful when high bandwidth is needed. On the other hand, cost describes how expensive it is to implement – as well as improve the resolution – of the ADC and is influenced by the complexity and number of hardware components required in the design.

Typical ADC methods demonstrate that an increase in speed of the solution will cause an increase in the cost. This is indicative of the trade-off between parallel and sequential logic, as parallel logic will be faster but will require more hardware components. For this article, I will give a brief outline of 3 key ADC solutions:

  • The first method that will be addressed is the Dual Slope, also known as the Integrating method. This method works by charging up an integrator circuit by the voltage being sampled for a fixed amount of time, then discharging the same circuit at a known reference voltage back to no-charge. By using a counter to track time for the discharge phase, the circuit is able to accurately derive a digital equivalent of the original analogue signal using Latex formula. Due to requiring the charging and discharging of a capacitor, this method is one of the slower methods used but also not very costly.
  • Next is Successive Approximation (SAR), which, as the name suggests, operates by estimating the digital output by testing each bit in the final representation progressively from the MSB to the LSB. At each step, it sets the current ‘result’ bit to HIGH (bit = ‘1’), performs a Digital-to-Analog conversion (DAC) and checks whether the analog equivalent is greater than the sampled analog voltage, setting the bit back to LOW (bit = ‘0’) if true then moves on to the next MSB. Doing this ensures that the resulting digital value is the closest binary representation that is still less than the sampled voltage. This method’s speed is typically faster than the ramping method, but has a greater cost as a payoff due to the more complex circuitry.
  • The last method mentioned is Flash ADC, one of the fastest ADC methods. A flash ADC is a group of parallel comparators which individually check the input voltage against reference voltage for all possible digital outputs and then uses a priority encoder to select the appropriate binary result. The cost of this method is the largest of the three as it requires enough components to perform all these voltage comparisons in parallel.
The internal working of BLUEtongue 2.0
The internal working of BLUEtongue 2.0

In addition to the methods described here, there are also interesting ADC solutions such as the Sigma-Delta, but we will leave that for the reader to explore.

ADCs on BLUEtongue

One of the primary uses of the ADC on BLUEtongue was to implement the swerve drive system. To ensure the system’s functionality, it was important for the real-time wheel headings to be known as accurately as possible. To achieve this, potentiometers (pots) were integrated into the front two shafts of the wheel rotators and fed back to the control board, where the analog read-out of the pot was converted into a digital signal that was then passed through to the on-board computer via USB.

In addition to the swerve drive, ADCs were also used in feedback systems for arm manipulation.


ADC on the PIC

For BLUEtongue v2.0 the control board consisted of a custom made PCB, housing the dsPIC33EP512MC806 microprocessor (PIC) from Microchip (Read more here). The ADC on the PIC used for the rover is an implementation of the SAR system, with a few additional features.

The PIC provided two independent SAR modules, the first module (ADC0) was able to operate in 12-bit resolution with one channel S&H (Sample and Hold, where the analogue input is captured for the length of the conversion) if desired, whilst both are able to operate at 10-bit resolution with 4 channel S&H.

The resulting conversions were stored in a dedicated 16×16-bit buffer (one buffer for each ADC module exists) allowing for convenient access upon completion. Furthermore, to signify that a conversion sequence has been performed, the PIC is able to generate interrupts or, alternatively, set a ‘done’ bit/flag. The former is useful for time-sensitive, synchronous data whilst the latter (which would be implemented through a form of polling) is less time-critical and better for asynchronous conversions.

For the purpose of the swerve drive, we implemented ADC1 in 12-bit resolution and used the ‘Channel Scan Select’ feature (which allowed the module to sequentially scan multiple ADC pins) to allow the best resolution possible whilst also providing the conversion requirements for the multiple data feedback sources. Furthermore, we used the interrupt method as feedback data for the swerve system constituted an urgent situation.

Programming the PIC

The following code demonstrates how the ADC was setup on the PIC.

// ** Code to setup adc for reading potentiometers ** //
// ** Uses the input scan select system to allow reading ** //
// ** of multiple analog inputs within a single module ** //

void setupADC1(void) {
    // Set appropriate pins as inputs (to read from the pots)
    TRISBbits.TRISB8 = 1;
    TRISBbits.TRISB10 = 1;
    TRISBbits.TRISB12 = 1;
    TRISBbits.TRISB15 = 1;
    TRISEbits.TRISE0 = 1;
    TRISEbits.TRISE1 = 1;
    TRISEbits.TRISE2 = 1;
    TRISEbits.TRISE3 = 1;

    // Setup the pins to read analog values
    ANSELBbits.ANSB8 = 1;
    ANSELBbits.ANSB10 = 1;
    ANSELBbits.ANSB12 = 1;
    ANSELBbits.ANSB15 = 1;
    ANSELEbits.ANSE0 = 1;
    ANSELEbits.ANSE1 = 1;
    ANSELEbits.ANSE2 = 1;
    ANSELEbits.ANSE3 = 1;

    // Set the control registers to zero, these contain garbage after a reset
    // This also ensures the ADC module is OFF
    AD1CON1 = 0;
    AD1CON2 = 0;
    AD1CON3 = 0;

    // clear ADC1 control registers: CON4, CHS0, CHS123 and CHSSH/L
    AD1CON4 = 0;
    AD1CHS0 = 0;
    AD1CHS123 = 0;
    AD1CSSH = 0;
    AD1CSSL = 0;

    AD1CON1bits.AD12B = 1; // Activate 12 bit adc.

    // *** CLOCK SETTINGS *** //
    //Changes the ADC module clock period for both conversion ad sampling.
    // Tad must be greater than 117.6 ns (electrical specs, pg560), T_CY is 1/70Mhz
    // Tad T_CY * (ADCS + 1)
    // Tad/T_CY - 1 ADCS
    // ADCS (117.6*10^-9)*(70*10^6) - 1
    // ADCS 7.232 ~ 8

    AD1CON3bits.ADCS = 0x0F; // T_AD = T_CY * (ADCS + 1)
    AD1CON3bits.SAMC = 0x1F; // Sampling for TAD * 14 (as required for 12-bit)

    // Auto-sampling, automatically end sampling and begin conversion
    AD1CON1bits.SSRC = 0b111;

    // Select the pins that will be cycled through via input scan select
    // NOTE: The ADC scans in ascending order of analog number, i.e.
    // if connecting an4, 9, 5, 12 the buffer will be filled:
    // 4, 5, 9, 12. Ensure any changes enforce this convention!
    AD1CON2bits.CSCNA = 1; // Activate channel scan select
    AD1CSSLbits.CSS8 = 1;
    AD1CSSLbits.CSS10 = 1;
    AD1CSSLbits.CSS12 = 1;
    AD1CSSLbits.CSS15 = 1;
    AD1CSSHbits.CSS24 = 1;
    AD1CSSHbits.CSS25 = 1;
    AD1CSSHbits.CSS26 = 1;
    AD1CSSHbits.CSS27 = 1;

    // Will need to interrupt after (N-1) sample/conversion sequences.
    // Where N = number of signals being read (e.g. an16 an24 = 2 signals = SMPI = 1)
    AD1CON2bits.SMPI = 7; //interrupt on sample conversion

    //automatically begin sampling whenever last conversion finishes, SAMP bit will be set automatically
    AD1CON1bits.ASAM = 1;

    // Clear interupt flag, set interrupt priority
    _AD1IF = 0;
    _AD1IP = 3;

    // Enable the interupt
    _AD1IE = 1;

    //enable ADC1
    AD1CON1bits.ADON = 1;

// ADC interrupt serve routine (ISR). This sets a variable so that the main function
// knows that a conversion has finished and can read from buffer.
void __attribute__((__interrupt__, no_auto_psv)) _AD1Interrupt(void) {
    _AD1IF = 0;
    adc_ready = 1;


The ERC 2016 team, posing with the rover. From left: (standing:) Jim Gray, Timothy Chin, Denis Wang, Simon Ireland, Nuno Das Neves, Helena Kertesz, (kneeling:) Harry J.E. Day, Seb Holzapfel
The ERC 2016 team, posing with the rover. From left: (standing:) Jim Gray, Timothy Chin, Denis Wang, Simon Ireland, Nuno Das Neves, Helena Kertesz, (kneeling:) Harry J.E. Day, Seb Holzapfel


Going forward, the Off-World Robotics team will continue to develop and expand its use of signal processing with the aid of ADCs for the drive system, as well as other key systems such as the fine control of the arm. The experience gained from programming on the microprocessor and implementing the ADCs has been very rewarding for me. The knowledge will also prove invaluable to the team as we look to enhance the embedded system for the next iteration of the rover, code-named NUMBAT, with a Controller Area Network ( will appear in a future article!). I hope you have enjoyed this write-up and found the series informative.

To view the entire embedded system repo, click here.

Thank you for reading, to keep up to date with BLUEsat and the Rover, like us on Facebook and stay tuned for more posts on this site. If you are interested in getting involved, you can find more here.