Sunday, November 17, 2013

Week 13: Miscellaneous Brainstorming

A good part of this week has been devoted towards researching additional info on various things which have been worked into other blog entries. So most of this week's documentation has been distributed amongst the other posts.

One notable thing I've been throwing around is the possibility of RobotC multithreading. This could possibly reduce the latency of a sensor access from the NXT user program's perspective. By spinning up a background thread whose job is to continuously poll attached sensors, the data will be more or less constantly updated and available during the main execution loop. This is slightly more efficient than my current method of only polling the sensors at the start of each execution loop iteration. And it would also be good to understand how to multithread on RobotC anyways.

After looking into it (15-20 minute jam session), RobotC has a relatively simple multithreading implementation. It's referred to in RobotC as "multitasking", and it involves creating separate "Task" routines and then kicking them off with StartTask().

task main()
{
     StartTask(Task1);
     StartTask(Task2);
}

task Task1()
{
    //Things
    while() ;
}

task Task2()
{
    //More Things
    while() ;
}

Code 1. That's literally all you need to do to create a separate thread.

As can be seen, it's a relatively painless affair. However I do urge caution, in ANY user program ANYWHERE too much multithreading can be dangerous and resource intensive. Without proper understanding of how to multithread correctly, it may just be simpler to keep things iterative. I'm fairly sure RobotC doesn't implement any "high-level" control of multithreaded constructs (Mutexes/Semaphores), so keeping critical sections safe lies entirely on the programmer.

I may pursue this further to implement background sensor polling.


Sunday, November 10, 2013

Week 11/12: IR Sensor

Going off of my previous brainstorming regarding possible sensors, I decided to begin work starting with the IR sensor idea.

POST-COMPLETION EDIT: So it's probably best for my code to speak for itself here (link to both files at the bottom). I'm going to do a breakdown of both the RobotC and Arduino codes, pointing out anything important of note. I should note that the NXT and Arduino are connected as previously described, with the I2C lines feeding into the A4/A5 analog pins on the Arduino. There is an IR sensor signal line feeding in to DIO pin 4 on the Arduino with a 330 Ohm resistor in series.

LIBRARY NOTE: The IR sensor requires a decoding Arduino library written by Ken Shiriff (https://github.com/shirriff/Arduino-IRremote), the instructions to install are included on the github.

NXT Code
This section is fairly straightforward. There is a main execution loop, main(), which continually polls the Arduino using PollIR() to retrieve a 32-bit IR code. Once retrieved the code is displayed on the NXT screen, and a particular tone is played if the code matches pre-determined values (I'm using a random remote control I had lying around. Other remotes will have different codes).

The guts of the PollIR() function are also pretty standard. As detailed in previous posts, a register selection packet is constructed using the I2Cmessage[] structure selecting register 0x01 on the Arduino. The packet is send, a 4-byte reply (IR codes are 4-bytes long) is requested and retrieved using readI2CReply(), and some bitwise reconstruction is performed to get the original code. -1 is used as a reserved code to indicate that no new data is available from the sensor.

Arduino Code
The Arduino is responsible for continually scanning for IR codes, utilizing the newly installed IR photodiode. The <IRremote> library provides the "irrecv" structure, initialized with the line "irrecv.enableIRIn()"; this also prompts the library to begin scanning in the background of the user program. During each execution loop this structure will be evaluated for IR codes, upon detection they will be committed to memory. The Arduino needs to be capable of storing multiple IR signals, recall the NXT is not necessarily polling the Arduino in realtime, and thus there needs to be some mechanism to hold unprocessed codes. I implemented this functionality using a linked-list queue, and the push() pop() functions manage access to this.

The Arduino's Wire library is configured to use address 0x0A, and the I2CHandleDataRequest() and I2CReceive() functions are attached as interrupt handlers to be called when data request or register selection packets are received respectively. Recall that digital sensors maintain register banks; this is emulated with a register_requested state variable, selecting between register 0x01 (Most recent IR Code) or 0x02 (length of IR processing queue).

 Mentioned previously is an idiosyncrasy of the Wire library, the Arduino will only transmit packets using 1-byte payloads. This means that any data must be transmitted as a series of disjoint byte packets. As IR codes are 4 bytes in length, I have a function constructIRArray() to take in a code and create a 4-element byte array for I2C transmission. Once this is transmitted, the RobotC code will perform reconstruction of the IR code.

One consideration to make is that I haven't put in any memory safeties. Here I'm presuming data will be processed in a timely manner, though if for some reason a massive number of IR codes were to accumulate without being polled by the NXT, there could ostensibly be memory errors as the IR queue will never be cleared.


Links to Code

Arduino Code - https://www.dropbox.com/s/ewd55d2vx574665/IR_Arduino.ino

NXT Code -  https://www.dropbox.com/s/8yq10d8isjexdst/IR_NXT_Program.c