IR and UART

 

Lab 3 : IR and UART

EEC 172: Lab #3 - IR and UART

Author : Kelly Su, Tony Xiao

Intro

The objective of this lab was to learn to use the Logic analyzer waveform signals to interpret and decode the type of code we have and determine how the waveform translates to binary code. This is used using interrupt handlers and timers to be able keep account of the lengths of signal changes and respond accordingly. Afterwards, we can convert the binary to buttons pressed and configure the behavior of the output text that is read. The interpreted letters and actions are displayed on the OLED that is connected to the CCS3200 LaunchPad. We also learned to have the two CCS3200 Launchpads communicate to each other and configure the two OLED screens to print out the messages each board receives from each other.

Background

The IR receiver has a very simple interface – power (Vs), ground (GND) and output signal (OUT). It reads signal from a IR remote control and convert it into electric output signal. The Out is connected to the GPIO on a CC3200 board so that we can decode it in the micro-controller.

The IR remote control is the device that is transmitting signals sent to the IR receiver. It is configured so that certain button presses emit certain signals that are unique to each button.

The Timer API allows you to start a timer, enable and disable the timer, load a value into a timer and get the value of the timer. The timers used could be 16 bit timers or 32 bit timers and could count down or up based on the configuration.

The UART Interrupts allow you to get and print a character to the OLED screen once it receives a signal from the Rx pin.

The GPIO Interrupts allow you to trigger an interrupt handler when a pin signal changes and allows you to clear the interrupt which is maintained using a interrupt status.

Goals

Part I: Capturing and Characterizing IR Transmissions using a Saleae logic

Connect the Logic analyzer to the circuit board with the IR transmission module and use the Data Formats for IR Remotes document to interpret the Saleae waveform. Figure out which type of coding is configured to the remote control. Test how the waveforms look for each button and what happens when a button is pressed consecutively multiple times.

Part II: Decoding IR Transmissions / Application Program

In this step, we needed to decode the waveform signal and convert it into binary in order to determine which button was pressed. Part II: Board to Board Texting Using Asynchronous Serial Communication (UART) We needed to have the two boards sending and receiving messages to/from each other. In order to do this, the Tx pin had to be hooked on the Rx pin of the other and vice versa. The letter that was outputted needed to correspond to the number of times the button was pressed, the letters needed to be displayed on the board sending the signal and when the ‘send’ button was pressed, the other board would be able to receive the signal at the bottom half of their board. The delete keys also needed to be able to signal a letter to be removed from the input CCS3200 Launchpad.

Methods

Part I: Capturing and Characterizing IR Transmissions using a Saleae logic

We figured out that our remote control was configured to have a ‘pulse length coding’ where the interval between each binary value was the same length and 1s were signified by longer periods of high signals while 0s were signified by shorter periods of high signals. Each button pressed gave us a start signal and an end signal and there was always a really long low signal after every button press despite being pressed consecutively. Our waveforms looks like this as follows for each button:

0. 0000 0010 1111 1101 0000 0000 1111 1111

1. 0000 0010 1111 1101 1000 0000 0111 1111

2. 0000 0010 1111 1101 0100 0000 1011 1111

3. 0000 0010 1111 1101 1100 0000 0011 1111

4. 0000 0010 1111 1101 0010 0000 1101 1111

5. 0000 0010 1111 1101 1010 0000 0101 1111

6. 0000 0010 1111 1101 0110 0000 1001 1111

7. 0000 0010 1111 1101 1110 0000 0001 1111

8. 0000 0010 1111 1101 0001 0000 1110 1111

9. 0000 0010 1111 1101 1001 0000 0110 1111

Last: 0000 0010 1111 1101 0000 0010 1111 1101 (delete)

Mute: 0000 0010 1111 1101 0000 1000 1111 0111 (enter)

Time durations of the high and lows of the signal: start

  • low: 9.036ms
  • high: 4.476ms

0s: low: 0.612ms high: 0.542ms

1s: low: 0.588ms high: 1.666ms

end time low: 0.580ms high: 39.94ms

We decoded the waveform into binary values, took note of the intervals in which each low / high signal occurred, as well as the pattern and intervals of the starts and ends of each button press.

Part II: Decoding IR Transmissions / Application Program

We used a falling edge detector to trigger an interrupt handler to decode the signals. We used an array called timeSeries[] to to keep track of all the times of when a falling edge occurs in the interrupt and we restart the timer for every button change. In order to do this, we keep a counter that acts as the index of the timeSeries[] array and the falling edge we are on in the sequence of a button. The counter always starts at 0 and only gets incremented when a start signal is detected which we use the start time interval calculated from the Logic analyzer to check. In other words, we only ever start storing the time values in the array when the difference between the previous and current matches the starting signals. From there a flag is set to signify start and the interrupt keeps storing the times when the handler is triggered up until the counter reaches 35 (which is what is needed to know the start, 32-bit code, and the end signals). Inside of main, a while loop is running infinitely to read in signals and keep jumping to the interrupt handler until the counter reaches 35. When the counter reaches 35, the while loop inside of main then executes the else statement inside to disable all interrupts while it calculates the difference between the falling edges that were stored in timeSeries[]. The counter sets back to 0 for the next round of buttons and the start flag is set back to 0 until another start is detected in the interrupt handler. While interrupts are disabled, the decoding happens in the decodeSignal() function to map the differences of the consecutive falling edges (stored in duration[]) to 1s and 0s. This binary is then converted to the associated button (0-9, mute or last) using the decodeBinary() function.

Part II: Board to Board Texting Using Asynchronous Serial Communication (UART)

For the consecutive button presses, we used a 2nd timer to measure the time difference between the two presses. The 2nd timer starts running once we decode the first button press, and stops when detected a start signal of the next button press. By subtracting those two values we can get the time difference. If the difference is smaller than a certain threshold value and the button pressed is the same as the last (we keep a state of the previous button pressed), we assume the user wants to change the current character. We then we remove the previous char displayed on screen and replace it with the new character in line (‘A’ => ‘B’, ‘B’ => ‘C’). When the difference is greater than certain threshold value we will print the same char twice (‘A’ => ‘A’ ‘A’).

We used UART interrupt handler function to receive and print one character at a time to OLED. We have a global character array that acts as character buffer. Whenever the button 0 - 9 is pressed, we store the decoded character into that buffer. Once the mute key has been pressed, we call UARTCharPut() in a for loop to send all the characters in the buffer through UART to output to the Tx pin. On the UART interrupt handler, we disable the UART DMA and clear the interrupt, and get character received by calling UARTCharGet() and print the character to lower screen.

When the message prints to the screen, while moving the cursor, we also check if the cursor is exceeds the OLED screen. If so, we change the cursor position so that the it can display the next char in a new line.

Discussion

The most difficult issue to solve with this lab was learning how to use the timer and interrupts and pinpointing the right times to use each interrupt handler. It was also very difficult to write the perfect code with no bugs to be able to get the right intervals to interpret as high or low and get the right binary consistently. It was also tricky configuring consecutive same button presses and keeping the state of the program by checking what last button has been pressed. Also, another problem we encountered was using the UART module interrupts to print the value to the other board’s OLED screen when a signal has been received through its MOSI pin.

Conclusion

We learned how to wire the IR receiver to send signals through a GPIO pin and how to wire the Tx pins and Rx pins between the boards. We learned how to use interrupt handlers (Timer Interrupt, UART Interrupt, GPIO Interrupt) and the Timer API to be able to handle signals received by the pins. We learned how to decode a signal using timers and falling edge / rising edge triggers. In addition, we learned how to send data through UART between two CC3200 launchpads and print the message to the OLED without delay (using printf could slow the program down and could change the program behavior).