This is just a placeholder for some ideas percolating in my brain. In fact, it gets more and more disorganized as I go through this, so if you're looking for coherent information, it ain't here. Once I get things figured out I'll re-organize into a tutorial.
For (so far) all of my 3-pound combat robots -- and most of those my students are building -- we're using the Scorpion XL speed controller. They've served us well.
It turns out these use an ATmega168 microprocessor, meaning they're in the same architecture family as the Arduino microcontroller and should be programmable by the same tools. So here's my thinking:
I'm curious if any of the Scorpion's jumper pins are just exposed digital I/O pins from the ATmega168.
What I can see:
From the above, I count 14 available pins.
Assumptions:
At most, I should have 13 pins available, and no more than 4 of them PWM-ready. So, off-by-one from the visible pin count. I bet that beside-Rx-solder-point is just a break-out for something else (judging from the traces, I suspect it's a +5v tap). And we know at least 2 of the available pins (the I2C pins) are analog.
Using a Scorpion XL with Pololu AVR programmer, add the sections below to the boards.txt and programmers.txt files.
In boards.txt:
scorpionxlAVR.name=Scorpion XL (ATmega168, 5v) AVR
scorpionxlAVR.using=pololu
scorpionxlAVR.upload.maximum_size=14336
scorpionxlAVR.upload.speed=19200
# scorpion xl does not have an external clock like Arduino, so
# fuse bits must reflect using the internal 8 MHz oscillator!
scorpionxlAVR.bootloader.low_fuses=0xe2
scorpionxlAVR.bootloader.high_fuses=0xdd
scorpionxlAVR.bootloader.extended_fuses=0xf9
scorpionxlAVR.bootloader.path=atmega
scorpionxlAVR.bootloader.file=ATmegaBOOT_168_diecimila.hex
scorpionxlAVR.bootloader.unlock_bits=0x3F
scorpionxlAVR.bootloader.lock_bits=0x0F
scorpionxlAVR.build.mcu=atmega168
# using internal atmega168 oscillator @ 8 MHz
scorpionxlAVR.build.f_cpu=8000000L
scorpionxlAVR.build.core=arduino
scorpionxlAVR.build.variant=standard
In programmers.txt:
######################################################################
# Orginal from b.cook ...
pololu.name=Pololu USB AVR Programmer
pololu.communication=serial
pololu.protocol=avrispv2
[My "good" scorpion and the "broken" one from work have identical firmwares.]
Verbose output (stock firmware)
avrdude: Version 5.11, compiled on Sep 2 2011 at 19:38:36
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2009 Joerg Wunsch
System wide configuration file is "../etc/avrdude.conf"
Using Port : COM5
Using Programmer : avrispv2
AVR Part : ATMEGA168
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PC2
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page
Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 512 4 0 3600 3600 0xff 0xff
flash 65 6 128 0 yes 16384 128 128 4500 4500 0xff 0xff
lfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
efuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
lock 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : STK500V2
Description : Atmel AVR ISP V2
Programmer Model: STK500
Hardware Version: 15
Firmware Version Master : 2.10
Topcard : Unknown
Vtarget : 4.6 V
SCK period : 3.3 us
Varef : 0.0 V
Oscillator : 3.686 MHz
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.02s
avrdude: Device signature = 0x1e9406
avrdude: safemode: lfuse reads as E2
avrdude: safemode: hfuse reads as DD
avrdude: safemode: efuse reads as 7
avrdude: safemode: lfuse reads as E2
avrdude: safemode: hfuse reads as DD
avrdude: safemode: efuse reads as 7
avrdude: safemode: Fuses OK
avrdude done. Thank you.
Note that a "1" means "not programmed" and a "0" means "programmed"
srec_cat scorpionxl-flash-factory.bin -binary -Output scorpionxl-flash-factory.atmel_generic
avr-objdump -D --target=binary --architecture=avr scorpionxl-flash-factory.bin > flash-factory.avr.asm
ATmega168 pins are organized into 8-bit registers called ports such that one port can store the I/O bits for up to 8 pins (one pin per bit). For example, Port B (PB7:0) contains eight general-purpose I/O pins. I'm searching through the ASM to find references to the memory addresses which map to ports (hacked up a Ruby script to do the job):
*The first value is used when accessing the register directly (IN, OUT, SBI, CBI instructions); the parenthetical value is if accessed as a direct SRAM memory location (ST, LD instructions).
On an I/O pin port, the following rules apply:
In interpreting the above table, if I found a 1 in a DDR register, I call that an output. If I find a 1 in a PORT register that is not already and output, I call that an input with the pullup resistor enabled. Anything else is marked as a potential input, i.e., it is definitely not an output but could simply be an unconnected input.
Scanning through the code I found writes to the following PWM-configuration registers:
I'm going to make a guess that either of OC0A or OC0B is one motor-enable output and either of OC2A or OC2B is the other. Reasoning: Take the 0x24 register as an example. What we know is that one or both of the PWM outputs was maybe configured, but we don't know if it's both or either specific one. The same goes for the 0xB0 register. Since we only have two motors, best guess is each register is only configuring one of its associated PWM pins.
Now, try to resolve that with what we know about outputs (two tables back)...and OUCH: all four of the PWM pins in question are configured as outputs. Some of them act as ICSP pins -- will the presence of an ICSP signal automatically override the PWM functions or is software required to differentiate?
After adding more support for arithmetic instructions, I got 241 written to 0x24 and 0 to 0x25. According to the chip specs, this says Arduino pins 5 and 6 are definitely set for PWM. Gonna make a big guess those are the motor enable outputs. Revised guess: 6 may be a PWM enable, but I'm thinking 5 may be an INH for the right motor. Updated Revised Guess: But what if all four INH inputs are PWM (which would allow LED brightness based on speed) and the IN inputs are binary????!?!?!? Yet another update: yes, the motor LEDs have brightness based on speed; I checked on my functional 'bot.
* ENC/rc refers to the 4-column-by-2-row pin header labeled "ENC", where r is the row and c is the column (zero-based)
**ISP/rc refers to the 3-column-by-2-row pin header labeled "ISP", where r is the row and c is the column (zero-based)
The ESC has four half-bridges (two per channel), probably from this family of devices. (Reasoning: he lists the BTN7960B half-bridge on the downloads page as a "key component", though he is not specific as to which device (Scorpion XL, XXL, or OSMC) to which it applies. Visual inspection of the chips on the board, and tests of certain pins, support that the XL uses this component.
The key pins for the half-bridge are shown below:
Pin descriptions:
I'm guessing that the motor LED's are in parallel with the motor power tabs with green oriented one way and red the other...and not driven directly by their own I/O pins.
It is possible to handle the forward, reverse, left turn, and right turn maneuvers with just two bits: one for the left IN's and one for the right IN's, assuming the dual IN's on each motor are the complement of each other. Since I seem to be running out of output-configured Arduino pins, I'm going to guess that A2 and A3 (or whichever of 3, 5, and 6 is not a PWM channel) is being used for this.