Emg 2009

From DIDEAS Wiki
Jump to: navigation, search


PIC32 connections

The documentation in this section is only for the PCB: KKNEE1.pcb (04-15-2010)

About the PIC32 PCB serial numbers


The primary power port is PJ1 (3 pins, 1.25mm space header). The pinout is "GND", "PWR", "GND". The voltage at PWR can vary between (~10V and 25.5V). The signal at this pin is distributed to many other connectors on the board (which may also serve as power inputs).

serial / programming

  • The Pic32 (v1) contains 5 total serial ports (of which 1 is SPI and 4 are UART).
    • The SPI port (PX1) and ISP port (PISP1) share serial signals; thus only one may be used.
  • The programming port is PISP1, is located on the bottom side, is 9 pin 1mm header, and is colored purple, black, red
    • For the EMG firmware this port no longer contains STDIO
    • Connect to the Microchip programmer via a PSER (the programming cable pins 1,5,6,9 pass to the same pin, pins 7 and 8 should cross)
    • A special cable is used to interface the PSER programmer to the ISP port. Specifically the Tx signal must be cut.
  • STDIO is routed to PSW1 (EMG firmware ).
    • Serial port is 4x (460,800) baud, 8 data bits, 1 stop, no parity.
    • PSW1 does not provide 3.3V, thus the PSER2h can not be used with this port.
    • For PSER1, a cable that reverses pins 2 and 3 is required

  • SWIFI / dataport telemetry is routed to PSW2 (EMG firmware )
    • PSW2 does not provide 3.3V, thus the PSER2h can not be used with this port.
    • wifi_fast.py -p <port number> -V p32_emg -X 3 -f xx
    • For PSER1, a cable that reverses pins 2 and 3 is required
    • For SWIFI, a straight cable is used, and connect to the MC port
  • PMC1/2 connect to the robot MC FUP port:
    • p32_emg firmware expects a 'dataport3e' type packed with a baud rate of 1.25Mbaud
    • connect to robot with a straight 9x1mm cable
  • PSC1/2 connect to the robot SC FUP port:
    • p32_emg firmware uses this for the V0 CMD-response protocol run on the robot
    • connect to the robot with a straight 9x1mm cable
    • the default robot baudrate for this port is 115200, however it may be changed by setting the robot key "SC_FUP_BAUDRATE" using the program "keys.py"
    • also - in "build_config.h" - the #def "xxxxx_FUP_BAUDRATE" would be set to the same value.
    • at present the baudrate is set to 833333
    • the robot only supports baudrates of 40e6/(16*i) some examples : (1.25mb, 833kb, 500kb, 230kb, 115kb)

PIC32 firmware

  • source code location [1]
  • Use the project p32_emg.mcp

LED status lights on P32

  • search code for "LED_INV", "LED_SET", "LED_CLR" for non #def uses of the LEDs
    • may wish to search for "LED_INV(0x"
#define LED_BACKGROUND_TGL   0x80   // orange
#define LED_MSG_VALID        0x40   // green2
#define LED_UART_EVENT       0x20   // red
#define LED_UART_QUEUE_EVENT 0x10   // blue
#define LED_TIC_TIMER        0x08
#define LED_MAIN_LOOP        0x04
#define LED_MSG_ERR          0x02
#define LED_CLUTCH           0x01   // white : used by the solinoid!
  • see the file io_led.h for the latest.

threads / tasks

The EMG firmware contains a background task (main loop), and interrupt based tasks at higher priority levels. The function "lib_task_add_callback()" is used to add a thread that will interrupt the main loop, but not each other. It operates at priority level 2. Its threads must operate cooperatively, which means that should not call delay functions or implment expensive algorithms. Generally they are coded as statemachines that implement "waits" changing state on some testable event. Anything that will take longer than ~1/2 the system loop interval (1mS) should be run from the main loop or a lower priority task.

Additional semi-non cooperative tasks may also be created. These would need to run at a level lower than the "lib_task" thread (2), but higher than the main loop (0).

main loop

The main loop for the EMG project is in the file "main_emg.c". As of present, there is mainly code to test / verify the systems operation. In general this file should not be modified by "users" as it will be modified by the developer.

user code

The file "emg_statemachine.c" is generally where the user should write their code.

The function "user_background()" is called from the main loop, and when there are free cycles. It may hog as many cycles as are available.

The function "user_statemachine()" is called from "user_system_statemachine()" which is called lib_task module at the system loop rate. It should return 'quickly'.

dataport (communicating with a computer and/or other microcontrollers)

How the dataport works

  • A "V3" dataport packet is implemented in the EMG firmware. Make sure that your "wifi_fast" supports this version. The "-X 3" command line option to wifi_fast.py is needed.
  • The output dataport data structure is defined in "dataport.h" - under the "P32_EMG" section.
  • This structure needs to precisely match the data structure specified in the "vlist" file used on the command line with "wifi_fast.py". (see support_scripts\vlist\p32_emg.vlist)
  • The "printf" command "DB_PRINTF" is used to output text over the "dataport" link.
  • The dataport telemetry is sent with the function "do_dataport()". It should be called synchronously with the user state machine.
  • At present, a thread runs the function "user_system_statemachine()" at 500 hz. This function reads data from the EMG queue, stuffs the "USER_DATAPORT_OBJ" and then sends it with the do_dataport call.


  • DP_PRINTF output is sometimes corrupted.
  • ISP UART and SPI are shared. Need to move ISP UART to different port.
  • this sharing also means that the MISO pin can be also driven by the ISP UART Tx signal. This appears to over drive the MISO signal - meaning that it is lost.

Robot Interface

There are generally two data connections between the Pic32 and the robot.

SC (MPD cmd-response protocol)

The file 'lib_v0_message.c' contains functions that exchange "MPD" messages with the robot. As this is a "command-response" protocol, before sending another command, the code should wait for a timeout or a response from the robot. Either way, probably 10mS should be allowed between commands. By default the robot uses 115kbaud on its SC port, however the round-trip transport delay is ~9.4mS at this data rate. The baudrate has been changed to 833Kbaud to reduce the total time to ~1.15 mS.

At present, the only MPD command supported is the "special command" (which is way the do_command.py -s command is typically used for.) A special command is a command number followed by upto 10 signed 32 bit numbers. The answer message has the same format. Command numbers 0-999 are routed to the SC, 1000-1999 to the MC, and 2000-2999 to the IMU. If 10,000 is added to a command to the MC, then the upper ~6 longs in the answer message will contain a number of motor controller sensor readings. See "hostcmds.h" in the MC directory for the data structure "HOSTCMD_GETDATA_4_STRUCT_T".

In the pic32 directory, the file "lib_v0_message.c" contains functions of the form: special_command(cmd), special_command1(cmd, v0), ... that can be used to send a command with data. Commands supporting upto 4 data values have been provided. It is easy to add commands to support additional numbers of arguments.

When an MPD valid command is received (ak the answer to the previous command), then the function "process_rx_mpd_message" in the file of the same name is called. At present, the only action is to output to STDOUT the command and its payload. Code could be added to call other functions or to stuff global sensor variables with the results of a command.

special commands and interesting robot firmware files

  • The processing of the special commands is done in the robot firmware. The following files may be helpful:
    • firmware\StateController\Infrastructure\tk_cmdset.c
    • firmware\MotorController\tk_cmdset.c
  • The MC statemachine state can be set with command 1421 <state>. The action taken by the state can be discovered in the file:
    • firmware\MotorController\mc_statemachine.c
  • The SC statemachine state can be set with command 170 77 <state>
    • See firmware\StateController\statemachine_H2.c
  • During bootup, the robot SC runs the "demux statemachine" which is in the file:
    • firmware\StateController\demux_statemachine.c
    • The special command "173 77 <state>" sets the DMSM state. State 6 is the normal run time state, and only from this state is statemachine_H2 called.

MC (dataport protocol)

The file 'lib_dataport_h20_rx.c' contains functions that receive telemetry from the robot MC FUP. At present the robot is using a "V2" data packet of format specified in the support_scripts\vlist\dataport3d.vlist file. Wifi_fast.py can also be used to receive and plot this data packet.

When connected to the Pic32, the function that decodes the "H20" packet is called "lib_dataport_h20_rx" and lives in the C file of the same name. lib_dataport_h20_rx() is called in a ISR thread when the Pic32 UART has received sufficuent data to fill a packet. The series of functions calls are:

  • io_pic32_uart_isr.c : THREAD_ASSERT_FOR_UART_EVENT // this causes the assertion of a medium priority ISR
  • pic32_threads.c : OC3Handler() // this is the function that responds to the ISR
  • main_emg.c : dp_uart_handler_thread3()
    • lib_datport_h20_rx.c : lib_datport_h20_rx() // decode the packet
    • if the packet is valid call lib_datport_h20_rx.c : stuff_remote_sensors_type2() // populate the global variable "rmt_sensors" with values received from the robot

The "rmt_sensors" global is declared in sensors.c with the type "REMOTE_SENSORS_T" which is defined in sensors.h. This datatype contains memeber named "raw" of type "DATAPORT_H20_T" which is defined in "h20_dataport_struct.h".

To access a robot sensor value (sent via the MC telemetry) from the "user code" use the construct: rmt_sensors.raw.<member name>

For example:

  • the SC state is "rmt_sensors.raw.state"
  • robot joint angle is : "rmt_sensors.raw.raw_xxxxx_angle_encoder"
  • robot motor angle is : "rmt_sensors.motor_encoder"

To access these values, be sure to include the header files:

  • #include "sensors.h"
  • #include "h2_dataport_struct.h" (which is likely included from sensors.h)

reading samples

The 24 bit ADC sequentially samples the n (upto 8) channels at upto ~20khz. When the conversion is complete, it is read via SPI and placed into a queue.

Samples can be read with:

ADS1258_DATA_T *ptr = ads1258_dequeue();
if (ptr) printf("%2.2x %2.2x %8.8x\n", ptr->status, ptr->channel, ptr->data);


The analog filter is a single pole LPF @ 800 hz, thus additional filtering may be required.

sample rate

  • see pages 18 to 21 of the datasheet: [2]
  • from the schematic, the clock freq appears to be 14.7456MHz.
  • probably best to use the SCOPE and monitor the SPI CS signal to determine the actual sample rate.


  • ADC reference voltage is +- 2.5V (total of 5V)
  • Is 24 bits (~16.7M)
  • Has ~10x gain
  • 1 LSB = ~5V / 16.7e6 / 10 = 29.8nV/lsb
  • base line of -1.03e6 counts -> 30.7mV

serial numbers

Serial numbers for the SPIEMG1 PCA:

  • 1 : hand build by CEB 100mA @ 15V
    • offset ~-200
    • Vcc 3.542e6
    • temp 1.046e6
    • gain 7.8589e6
    • ref 9.865e5
  • 2 : Ltronics 9-25-2010 50mA @ 15V
    • offset ~-1700
    • temp 1.032e6
    • gain 7.8672e6
    • ref 9.804e5

  • 3 : Ltronics 9-25-2010
    • Doesn't work. Verified has clock.
    • found 3 open pins on ADS1258. Fixed.

dsPIC firmware

dsPIC firmware development:

  • Use the workspace:


  • and select the project:


spiemg1 SCH/PCB

  • 8 channel PRE-AMP style EMG amplifier with SPI interface
  • SCH [3]
  • SCH for 3.3V switcher : [4]
  • SCH for 5.4V switcher : [5]

assembly instructions

  • Start by assembling the 3.3V switching regulator and then testing it by verifying 3.3V at TP7. This module has reference designator in the 80s and physical reside in a tight location of the top side of the PCB.
  • To power the 3.3V switcher you'll need to apply ~5V to V.PROT from a ~100mA current limited supply. A successful test is the output of 3.3V, with nothing getting hot. To apply power, you may wish to install P1, F1, and D1 and use one of my power pole to 1.25mm adapters.
  • Next assemble the 5.4V switcher (refdes 90s) and test with ~7V. Verify ~5.4V at TP6.
  • Assemble the -5V switcher (UN1 and support components) and test with ~7V. Verify ~-5V at TP10
  • Assemble the +- 2.5V linear regulators (UA1, UA2, and support). Verify +-2.5V at TP8 and TP12.
  • Assemble the ADC voltage reference (UR1, UR2 and support). For UR2 use REF3312 in the kit. Verify at TP18 that you see -1.3V WRT to GND, or 1.2V WRT to the -2.5V.
  • At this point, it should be safe to assemble the primary IC US1 and the remainder of the PCB.

paconn1 SCH/PCB

known issues

  • silk screen for PACONN1 doesnt show connector orientation
  • V.FUSED net isn't driven on EMG
  • Pin 1 of the 2x10 connectors is on the right side.




  • Passive electrode amp: AD8228 PDF
  • Linear Tech LTC2053 : PDF
  • TI ADS1298 for bio amps : PDF