From e4005ab0aacca024871354677f424379205fbedf Mon Sep 17 00:00:00 2001 From: AJ Keller Date: Thu, 14 Apr 2016 12:38:53 -0400 Subject: [PATCH] ADD troubleshooting section, ENH various grammer/spelling, .gitignore --- .gitignore | 1 + software/04-OpenBCI_Radio_Firmware.md | 14 ++++---- tutorials/02-Upload_Code_to_OpenBCI_Board.md | 38 +++++++++++++++----- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 63123fb..2df7cd6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_store +.idea diff --git a/software/04-OpenBCI_Radio_Firmware.md b/software/04-OpenBCI_Radio_Firmware.md index 0af1c51..1f5684a 100644 --- a/software/04-OpenBCI_Radio_Firmware.md +++ b/software/04-OpenBCI_Radio_Firmware.md @@ -7,16 +7,16 @@ OpenBCI comes with a RFduino module on-board for communication, and an RFduino b RFduino modules are built on a Bluetooth System-On-Chip radio from Nordic [nRF51822](http://www.nordicsemi.com/eng/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF51822), and we are using the Gazelle stack, which gets us faster data transfer rates than using the BLE stack. ##Features and Limitations of Gazelle -The Gazelle stack is a proprietary high-speed protocol from Nordic Semi. The folks at RFduino wrap it in thier Arduino compatible library and call it RFduinoGZLL. it makes high speed communication possible, but it still comes with some limits. +The Gazelle stack is a proprietary high-speed protocol from Nordic Semi. The folks at RFduino wrap it in their Arduino compatible library and call it RFduinoGZLL. it makes high speed communication possible, but it still comes with some limits. * Radio Packets are 32 bytes max * The Packet buffer is 3 packets deep * Fastest usable baud rate is 115200 (see below for notes) -The Device Radio (on OpenBCI Board) can send any time it likes, but the Host Radio (on Dongle) can only send on the acknowlegement. In other words, If the Host wants to send something it has to wait for a packet from the Device, and then it can send its message on what is called the acknowlegement, a responce that tells the Device that the packet was received. So, when the radios are 'idle', I have the Devide sending a NULL packet (packet with no data) every 50mS. That timing seemed to be a sweet spot for my purposes, and makes it possible for either side of the radio link to initiate a conversation. +The Device Radio (on OpenBCI Board) can send any time it likes, but the Host Radio (on Dongle) can only send on the acknowledgement. In other words, If the Host wants to send something it has to wait for a packet from the Device, and then it can send its message on what is called the acknowledgement, a response that tells the Device that the packet was received. So, when the radios are 'idle', we have the Device sending a NULL packet (packet with no data) every 60mS. That timing seemed to be a sweet spot for our purposes, and makes it possible for either side of the radio link to initiate a conversation. ##Uploading Over-Air With avrdude -On a basic level, the radio link that we use needs to act as close to a transparent UART as possible. That means that any serial message, wheather it's one byte or 128 bytes, needs to get from the PC to the OpenBCI Board (and back) as if the radio modules weren't even there. The first and most important problem to solve was enabling the upload of new code to the ATmega and PIC32. During the Summer of 2014, I put together an Instructable to document the work done on this front +On a basic level, the radio link that we use needs to act as close to a transparent UART as possible. That means that any serial message, whether it's one byte or 128 bytes, needs to get from the PC to the OpenBCI Board (and back) as if the radio modules weren't even there. The first and most important problem to solve was enabling the upload of new code to the ATmega and PIC32. During the Summer of 2014, we put together an Instructable to document the work done on this front [Program Arduino Over RFduino](http://www.instructables.com/id/Program-Arduino-Over-RFduino/) @@ -26,9 +26,9 @@ That code formed the backbone of the OpenBCI radio firmware. Here's a list of th * Time-out on the Serial port to determine the end of Serial message * First byte of the message reserved for Packet check-sum -Avrdude uploads code to ATmega328 with UNO bootloader in 128 byte pages, and the PIC32 with chipKIT bootloader uses 256 byte pages. The Host needs to make sure all of the bytes get through, so it uses a timer. If the UART is idle for more than 2mS, it will determine that the message is complete, and then put it on the radio. When sending large amounts of data, the firmware stores it in a 2D array, or matrix. Our firware uses 20 32byte arrays to 'stage' whatever comes in on the serial port. While the UART is active, the firmware keeps track of how many 32byte packets are going to be sent, and then sets the very first byte of the very first packet to that value. The RFduino on the recieving side always checks that very first byte in order to know how many packets to expect. +Avrdude uploads code to ATmega328 with UNO bootloader in 128 byte pages, and the PIC32 with chipKIT bootloader uses 256 byte pages. The Host needs to make sure all of the bytes get through, so it uses a timer. If the UART is idle for more than 2mS, it will determine that the message is complete, and then put it on the radio. When sending large amounts of data, the firmware stores it in a 2D array, or matrix. Our firmware uses 20 32byte arrays to 'stage' whatever comes in on the serial port. While the UART is active, the firmware keeps track of how many 32byte packets are going to be sent, and then sets the very first byte of the very first packet to that value. The RFduino on the receiving side always checks that very first byte in order to know how many packets to expect. -The other basic thing we need to do is have a way for the RFduinos to communicate to eachother special messages that the PC and ATmega (or PIC32) don't see. These 'radio only' messages are used for sending the reset command to the ATmega, and for keeping the radios on the same page when uploading to the PIC32. Radio only messages are always packets that have only one byte in them. Any other packet will have at least two bytes (Packet Check-Sum + Data Byte) +The other basic thing we need to do is have a way for the RFduinos to communicate to each other special messages that the PC and ATmega (or PIC32) don't see. These 'radio only' messages are used for sending the reset command to the ATmega, and for keeping the radios on the same page when uploading to the PIC32. Radio only messages are always packets that have only one byte in them. Any other packet will have at least two bytes (Packet Check-Sum + Data Byte) ###8bit Board @@ -75,7 +75,7 @@ The Arduino UNO bootloader runs when the ATmega 'wakes up' from reset. Back in t -The version of chipKIT's bootloader that we're using does not have an automatic reset like the 8bit Board does. However, we still need to keep track of when the user wants to upload code to the PIC. To do this, we have the Device monitor a pin on the PIC. RFduino pin 5 is connected to PIC pin 12(which is also known as the PGC pin to PIC programmers). The PIC pin 12 goes HIGH when it is in bootloader mode. To [upload to 32bit OpenBCI](http://docs.openbci.com/tutorials/02-Upload_Code_to_OpenBCI_Board#upload-code-to-openbci-board-32bit-upload-how-to), press the RST button, then press and hold the PROG button while you release the RST button. Takes coordination! Users will activate bootlaoder mode in the chipKIT before pressing the upload button on mpide. When the Device radio feels this pin change, it sends a special character to let the Host (Dongle) know. This is important because we found that uploading to the PIC can be prone to errors if the code is trying to do *anything* else during the process. +The version of ChipKIT's bootloader that we're using does not have an automatic reset like the 8bit Board does. However, we still need to keep track of when the user wants to upload code to the PIC. To do this, we have the Device monitor a pin on the PIC. RFduino pin 5 is connected to PIC pin 12(which is also known as the PGC pin to PIC programmers). The PIC pin 12 goes HIGH when it is in bootloader mode. To [upload to 32bit OpenBCI](http://docs.openbci.com/tutorials/02-Upload_Code_to_OpenBCI_Board#upload-code-to-openbci-board-32bit-upload-how-to), press the RST button, then press and hold the PROG button while you release the RST button. Takes coordination! Users will activate bootloader mode in the chipKIT before pressing the upload button on mpide. When the Device radio feels this pin change, it sends a special character to let the Host (Dongle) know. This is important because we found that uploading to the PIC can be prone to errors if the code is trying to do *anything* else during the process. 32bit DEVICE BOOTLOADER MODE CODE @@ -111,7 +111,7 @@ The version of chipKIT's bootloader that we're using does not have an automatic } ##Passing OpenBCI commands -OpenBCI uses ASCII commands to control the board. Setting up the SD card, changing ADS channel settings, turning on and off the data stream, are all done with a simple command set. One of this issues with this simple system, is that sometimes it becomes easy for noise to creep in. We found that during data transmission mode, there would be occasional glitches, where the PIC or ATmega would appear to recieve a command that we did not send (!). In order to get around this, we established what Conor dubbed 'The Burger Protocol'. What this means is that any time the PC or other controlling program sends a command character (meat), the Host RFduino will insert a '+' before and after it (buns). This way, the ATmega or PIC will not get tricked that extraineous noise on the UART is a command. The RFduinos 'know' when a command is being sent, because the OpenBCI commands are always only one character. Anything longer that 1 byte will not be burgerized. In the example at the right, the serialIndex[0] variable holds the number of bytes that are to be sent from the buffer. In this case, it is equal to 2 when there is only 1 bytes sent from the terminal or controlling program, because the first byte in the array will always be reserved for the packet check sum. You can see on the right that the message byte (meat) gets moved from serialBuffer[0][1] to serialBuffer[0][2], and then surrounded by '+' characters (buns). As a part of this process, the command byte gets 'sniffed' by the Host and Device RFduinos to see if the OpenBCI board is entering or leaving Streaming Data Mode. The controlling program sends a 'b' to begin streaming data, and an 's' to stop streaming data. RFduinos need to know this in order to change their behavior and stream the data at high speed. +OpenBCI uses ASCII commands to control the board. Setting up the SD card, changing ADS channel settings, turning on and off the data stream, are all done with a simple command set. One of this issues with this simple system, is that sometimes it becomes easy for noise to creep in. We found that during data transmission mode, there would be occasional glitches, where the PIC or ATmega would appear to receive a command that we did not send (!). In order to get around this, we established what Conor dubbed 'The Burger Protocol'. What this means is that any time the PC or other controlling program sends a command character (meat), the Host RFduino will insert a '+' before and after it (buns). This way, the ATmega or PIC will not get tricked that extraneous noise on the UART is a command. The RFduinos 'know' when a command is being sent, because the OpenBCI commands are always only one character. Anything longer that 1 byte will not be burgerized. In the example at the right, the serialIndex[0] variable holds the number of bytes that are to be sent from the buffer. In this case, it is equal to 2 when there is only 1 bytes sent from the terminal or controlling program, because the first byte in the array will always be reserved for the packet check sum. You can see on the right that the message byte (meat) gets moved from serialBuffer[0][1] to serialBuffer[0][2], and then surrounded by '+' characters (buns). As a part of this process, the command byte gets 'sniffed' by the Host and Device RFduinos to see if the OpenBCI board is entering or leaving Streaming Data Mode. The controlling program sends a 'b' to begin streaming data, and an 's' to stop streaming data. RFduinos need to know this in order to change their behavior and stream the data at high speed. 8bit EXAMPLE OF BURGER PROTOCOL ON HOST RFduino with COMMAND SNIFFING diff --git a/tutorials/02-Upload_Code_to_OpenBCI_Board.md b/tutorials/02-Upload_Code_to_OpenBCI_Board.md index ea61552..13c4efb 100644 --- a/tutorials/02-Upload_Code_to_OpenBCI_Board.md +++ b/tutorials/02-Upload_Code_to_OpenBCI_Board.md @@ -57,9 +57,9 @@ When you are happy with the code, simply press upload to program the OpenBCI 8bi ![OpenBCI Dongle](../assets/images/dongleConnection.png) -Make sure that the slide switch on the OpenBCI Dongle is switched to the GPIO6 selection. If it's on the other side, it will try to program the Dongle-mounted RFduino! +***Note***: Always plug the Dongle into the PC before powering the Board because the Host (RFduino on the Dongle) must be powered before the Device (RFduino on the Board). -Next, install the version 1.6.5 of Arduino IDE which can be found here: +First, install the version 1.6.5 of Arduino IDE which can be found here: https://www.arduino.cc/en/Main/OldSoftwareReleases#previous @@ -88,6 +88,8 @@ http://chipkit.net/wiki/index.php?title=ChipKIT_core Open the OpenBCI_32bit sketch from the File -> Sketchbook dropdown. Then select OpenBCI 32 from the Board drop-down menu. +Make sure that the slide switch on the OpenBCI Dongle is switched to the GPIO6 selection. If it's on the other side, it will try to program the Dongle-mounted RFduino! Now is a good time to plug your Dongle in and power down the Board. + ![serial_port](../assets/images/PortSelect.png) Select the correct serial port for your OpenBCI Dongle. @@ -98,16 +100,36 @@ Select the correct serial port for your OpenBCI Dongle. * On Linux, it will be different. - -When you are happy with the code, you will have to put the 32bit board into bootloader mode. We don't have a way to remotely reset the chipKIT compatable IC, so you have to do it manually. +When you are happy with the code, you will have to put the 32bit board into bootloader mode. We don't have a way to remotely reset the chipKIT compatible IC, so you have to do it manually. ![reset_program](../assets/images/RST_PROG.png) -* First, press and hold the RST button -* Then press and hold the PROG button -* Then, release the RST button while still holding the PROG button down -* OK, now you can release the PROG button +* Power OFF the OpenBCI Board. +* Press down both RST and PROG buttons at the same time. +* Power ON the OpenBCI Board. +* Release the RST button while still holding down the PROG button. +* Release the PROG button. ![Upload32](../assets/images/Upload32.png) Now you should see the blue LED on the 32bit board blinking pleasantly. Press the upload button on the Arduino IDE. That's it! You will see some blinky lights on the Dongle, and after a short while, the Arduino IDE will tell you that it's done. Happy Hacking! + +## Troubleshooting + +If the upload fails with `No Target Found`: + +1. Unplug the Dongle and Device. +2. Plug the Dongle into your computer. +3. Plug the Device into your computer. +4. Put the device into bootloader mode. +5. Try upload again. + +If the upload fails with `Program Flash Failed` it's due to the Arduino IDE not being able to read from the serial port fast enough possibly do to resource starvation or overall computer power. We recommend taking the following actions: + +* Keep the Board and Dongle physically close to each other during the upload. +* Keep the Arduino IDE open, front and center and don't use any other programs during the upload. +* Close all open programs such as (Google Chrome, MS Word, etc...) and only have the Arduino 1.6.5 IDE open during upload. +* Restart your computer and don't open any other programs other than the Arduino 1.6.5 IDE used for programming. +* If all else fails, find a friend with a more powerful computer and do the uploading from their computer. + +In extreme conditions, if you have tried all five of the above methods and still can't upload, then you can try to increase the Device's polling time [in the RFduino Device firmware code](https://github.com/OpenBCI/OpenBCI_Radios/blob/master/OpenBCI_32bit_Device/OpenBCI_32bit_Device.ino#L41). Increase `pollTime` incrementally (by about 5ms) until the upload succeeds. Upload the new radio code to the Device ([see tutorial](http://docs.openbci.com/tutorials/03-Upload_Code_to_OpenBCI_Dongle#uploading-device-firmware-to-openbci-boards-program-device-radio-with-openbci-dongle)). After you are satisfied with the uploaded code. You should set the Device's `pollTime` back to 60mS to remain compatible with existing drivers.