Wednesday, March 16, 2016

I2C design error

So, when I laid out the Wisp1 board, I was confused about whether the STM processor could provide integrated pull-up resistors for the I2C bus, or whether I would need to install external pull-ups.  I set the issue aside as I was doing the schematics, and promptly forgot about it entirely.  I went on to have the boards built, and oops, forgot about the pull-ups.

Well, not surprisingly, I was having problems with I2C not working.  After reviewing the code a dozen times over, I finally realized my mistake.  I kludged in a few pull-ups on the board, in a very snug (and not terribly pretty soldering job.  I stood a few 4.7k resistors on end at the end of a pair of capacitors that were on a VCC trace.  I ran the wires from the top of the resistors over to the I2C pins on the processor.  It was tricky, but I got 'em in there!


Having added the pull-ups, I was still having problems talking to the Si5351 chip.  It wasn't responding.  I looked on the 5351 end of things, and found that he TCXO was making a nice 26Mhz waveform on the TCXO side of the decoupling capacitor, but on the 5351 side, it wasn't making any signal.  I fooled with that for a while, thinking maybe the oscillator signal wasn't getting to the 5351 due to a cold solder joint or something.  I tried swapping my 0.47uF cap with a 100pF cap.  No joy.  I swapped that for a 0 ohm resistor, and suddenly there was no oscillation on either side.

Hmm.... was something wrong with the 5351, which was screwing up the Oscillator?   I went over to the 5351 and looked at things more closely.  All of the solder joints looked fine.  No shorts.  Getting nervous now, I decided to consult the datasheet.  Was I maybe putting the oscillator into the wrong pin?

It didn't take long for me to have an outright panic.  All the pinouts were wrong on the board!   After another moment I realized the problem, and did a serious face-palm.  I had installed the 5351 chip 180 degrees around.  The pins were out of order simply because the chip was on backwards.  Doh!

With a quick puff of hot air and flux, I flipped the chip around.  I fired up my debugger so that I could confirm the oscillator was now oscillating.  Lo and behold, before I could even pick up my test probe, I saw diagnostic messages from my I2C code scrolling up the screen.  The processor was talking to the chip!

I can now continue on with coding and debugging.  I'll have to look at my debugs more closely, and look at the pinouts.  I may have blown up the 5351 to some degree, so I'll be skeptical of things until I see it work.  It'll be easy enough to swap if I need to.

 In the meantime, I've already done a "RevB" spin of the board with the pull-ups in place, and a pull-down added to the 1v8 regulator, which I discovered was missing previously.  I guess I just have a mental block about pull-ups and pull-downs! OSH Park has already whisked the boards off to China for manufacture.  I didn't move too many parts around, so I'll just use my RevA stencils, and manually paste the (6) 0603 parts that were added/moved.  I expect once I finalize the design, I'll be panelizing the boards and ordering them in 0.8mm, at which point I'll order a stainless steel stencil to use on my tooling block.

Onward!

Sunday, March 6, 2016

Wisp1 assembly and first problem

The Build

The Wisp1_RevA boards arrived on Friday.  After some preliminary tests of a bare board to assure that VCC and Ground didn't seem to have any obvious shorts, and the ground pads all seemed to be interconnected, I went ahead and stuffed the board.





Weights and measures

Board, no components6.1g
Board, with components7.9g


Cleanup and VCC test

Some initial continuity tests indicated a short between VCC and GND.  After some fiddling, I found a hairline bridge on one of the processor legs, and cleaned it up.  Once power was applied, I found VCC at 2.06 volts.  Oops, I forgot to adjust resistor values in the voltage divider for 2.5 volts.  I had worked out the math, but I hadn't adjusted the values in the schematic.  I adjusted my schematics, BoM and swapped the resistors.

Current Measurement - Uh oh

Then the trouble began.  I did a current measurement, and found the board to be drawing 42 mA.   That's very high for a board with no code loaded, and nothing running.  It took an hour or so of removing parts by process of elimination before I found the problem was related to the 1.8v voltage regulator.  Once removed, the current draw dropped to almost nothing.

This regulator feeds the TCXO.  It should be feeding 1.8v into both Pad 6 (VCC) and Pad 2 (Enable). Poking around, it appears that pad 2 was isolated, and pad 6 was shorted to ground.   This turns out to be a direct result of a problem I had in the schematic earlier.  

The Source of the Problem

Note the +1V8 net connecting to the Enable line.  When I initially set things up, I inadvertently failed to connect the net to Pad 2.  It all appeared correct, but if you look carefully, you'll see that Pad 2 is NOT lit up in blue.  The ends are touching, but the software didn't link Pad 2 to the +1V8 net.




This glitch manifested when I tried to do the board layout, and found Pad 2 isolated.  I manually fixed it, but the next time I synchronized the schematic to the board layout, the connections went away again.

 

I fixed it a second time in the board layout (not realizing the underlying issue in the schematic) and generated the gerbers.  Unfortunately, the gerbers had the issue in them, as seen above.  I didn't realize it.

This is what the gerbers should have looked like:



 

Unfortunately, the schematic problem was detected at the 11th hour, just before I sent the Gerbers out to OSH Park.   I fixed the issue in the schematic, but I suspect I did not regenerate gerbers, since my board layout looked OK (with manual edits) when I had done it previously.  Either that, or I simply had a clerical error, and didn't copy the latest gerbers into the Zip file for OSHPark before sending them off.  Doh!

The drill file had vias, but there was no trace from Pad 2 to the via, nor between the vias.   The via beside Pad 2 just connects the ground planes of the top and bottom layer.  Unfortunately, the via between the regulator and pad 6 pierces the +1V8 trace on the upper surface, and the ground plane on the lower service.  That's the short.


The Kludge

I drilled out the via on the trace to Pad 6.  By doing so, it un-shorted VCC from ground.   


Then, I used some 40ga magnet wire to interconnect Pads 2,6 and the +1V8 source from the regulator.  Note, there is some exposed ground plane near Pad 2, but there is no short there.


I reinstalled the oscillator and checked for shorts as best I could.  Seeing no problems, I reinstalled the regulator.  Voila!  The board now drew 1.04ma.  This makes sense.  The Oscillator is rated at 1.5ma at 1.8v.  We would expect to see less from the 4.2v source voltage.


Having fixed the problem from the gerbers, the next problem to solve was that I botched the design, and should have had a pull-down resistor on the Enable line for the 1.8v regulator.  I kluged this by installing a 10k ohm 0402 resistor between the GND and ENABLE pins on the regulator.  You can see it on the bottom right below.


Having made that correction, the board was now drawing 0.08ma.

I reinstalled the CPU and GPS chips.  Measurements are listed below.


MeasurementResult
Resistance: J1.  Board fully built.670k ohm
Resistance: J2.  Board fully built.73k ohm
Current Draw (4.2v in).  No CPU, no GPS, 1v8 regulator off.0.08 ma
Current Draw (4.2v in).  No CPU, no GPS, 1v8 regulator on.1.04 ma
Current Draw (4.2v in).  CPU, no GPS, 1v8 regulator off.0.40 ma
Current Draw (4.2v in).  CPU, GPS, 1v8 regulator off.0.43 ma

It's time to write some code!!













Tuesday, March 1, 2016

Wisp1 telemetry

There are several encoding schemes being used, out there, to encode telemetry data into WSPR transmissions.  They all involve sending a second WSPR packet, with a bogus callsign.  The callsign is legal within the WSPR protocol, but uses characters in some positions which result in illegal ham callsigns.  This makes the telemetry packets easily distinguishable in the WSPR stream.

I've devised my own scheme, documented below, which is heavily based on the one used by VE3KCL, which he documented heavily in his S-4 flight blog.   My wisp1 telemetry makes several modifications.  I'll document them below.

My pico balloon data will be encoded into two WSPR transmissions, which is fairly standard for picos.  As a refresher, a typical WSPR transmission might look something like this:

     KD2EAT FN12 27

The fields include Callsign, Grid locator, and a power level.  There are 19 discrete values permitted in in the power level field.

Primary packet

The first modification is to re-purpose the power level field in the WSPR packet as an "Altitude" indicator. Each of the 19 discrete values will represent 1000 meters of altitude.   The altitude mapping ends up looking like this:

DBM Meters
0 0
3 1,000
7 2,000
10 3,000
13 4,000
17 5,000
20 6,000
23 7,000
27 8,000
30 9,000
33 10,000
37 11,000
40 12,000
43 13,000
47 14,000
50 15,000
53 16,000
57 17,000
60 18,000

So, the packet above indicates that the balloon is flying at 11,000 meters.  This provides altitude data in one packet with no additional modifications to the protocol, if desired.  It provides for altitudes from 0-18,000 meters (59,055 feet).

Secondary Packet

This is where the rubber meets the road.  We are encoding a lot of data in the callsign field, as well as the power field.  However, in this wisp1 version of telemetry, the grid square is NOT used to carry telemetry data.  This means that, though the callsign will be bogus, the telemetry data will appear in the same grid square as the primary packet.  It is assumed that the same data will be used to generate BOTH the primary and secondary packet, since the altitude encoding in the primary packet is refined by the telemetry packet.

Before going into the telemetry available, let's look at the amount of data we can encode.

The callsign consists of 6 positions with potential values as follows:

Position Possible Values Use in Wisp1 Number of Values
1 0,Q Telemetry Flag 2
2 A-Z,0-9 Data 36
3 0-9Telemetry Flag 10
4 A-Z Data 26
5 A-Z Data 26
6 A-Z, space Data 27

Positions 1 & 3 allow for 2*10 = 20 possible values.  This allows for up to 20 pico flights to be in operation simultaneously without colliding, provided everyone cooperates and uses a unique pair of characters in those two positions.

Positions 2,4,5,6 allow for 36*26*26*27 = 657,072 possible values.

The "Power" field accounts for another 19 possible values,   19 * 657,072 = 12,484,368 possible telemetry values.

Within those possible values, I encode the following parameters:

Telemetry Possible Values Granularity Number of Values
Grid Char 5 A-X One Character 24
Grid Char 6 A-X One Character 24
Altitude Granular 0-666 333 meters 3
Temperature -45c - 5c 5c 11
Lipo Battery 3.2v - 4.8v 0.2v 9
Solar Cell 0 - 1.2v 0.2v 7
Satellites 0-9 1 10

This scheme allows for 24*24*3*11*9*7*10 = 11,975,040 needed values, which comfortably fits into the 12,484,368 available.

Calculating the value (example)
  • Actual telemetry:
    • Callsign: KD2EAT
    • Grid: FN12MX
    • Altitude: 8,500m
    • Temperature: -21c
    • Lipo: 4.35v
    • Solar: 0.8v
    • Satellites: 6
    • Pico tag letters "0" and "9"
  • The two WSPR packets for this data would be:
    • KD2EAT FN12 27
    • 0S9SBU  FN12  17
How we got Packet 1
  • Packet 1 is standard WSPR except the DBM field.  27 DBM encodes the value "8", for "8,000 meters" (See the table above).  So we know the balloon is between 8000-9000 meters.  We'll get more granularity from packet 2.  
How we got Packet 2
  • Each telemetry value is converted to an integer.  Ex:
    • Grid Char 5: "M" = 12
    • Grid Char 6: "X" = 23
    • Altitude Granular:  8,500 (8000 was in packet 1.  500 remains).  Rounds to 666.  = 2
      • values: (0=0, 333=1, 666=2)
    • Temperature:  -21c.  Rounds to -20c.  = 5
      • (-45=0, -40=1, -35=2, -30=3, -25=4, -20=5, etc)
    • Lipo: 4.35v.  Rounds to 4.4v = 6
      • (3.2=0, 3.4=1, 3.6=2, 3.8=3, 4.0=4, 4.2=5, 4.4=6, 4.6=7, 4.8=8)
    • Solar: 0.89v.  Rounds to 0.8v. = 4
      • (0.0=0, 0.2=1, 0.4=2, 0.6=3, 0.8=4, etc)
    • Satellites: 6 = 6
  • Making the big number
    • Big number =
      • num = grid5
      • num = num * 24 + grid6
      • num = num * + altitude
      • num = num * 11 + temperature
      • num = num * + lipo
      • num = num * + solar
      • num = num * 10 + satellites
    • For this example, the telemetry would be:
      • 12
      • 12 * 24 + 23= 311
      • 311 * + 2 = 935
      • 935 * 11 + 5 = 10,290
      • 10,290 * + 6 = 92,616
      • 92,616 * + 4 = 648,316
      • 648,316 * 10 + 6 = 6,483,166
      • 6,483,166
Making WSPR from the telemetry value
  • WSPR char 1: "0" or "Q".  Hard coded.
  • WSPR char 3: "0" - "9".  Hard Coded.
  • Remaining WSPR Characters, as follows:
    • Num = telemetry number as above.
    • DBM = num % 19; num = num / 19      // Values 0,3,7,10,13,17,20,23,27,30,33,37
    • WSPR6 = num % 27; num = num / 27  // Values a-z,space
    • WSPR5 = num % 26; num = num / 26     // Values a-z
    • WSPR4 = num % 26; num = num / 26     // Values a-z
    • WSPR2 = num (should be 0-35)              // Values a-z,0-9
WSPR encoding our telemetry above
  • Telemetry value: 6,483,166
  • DBM = 6,483,166 % 19 = 5 = "17 DBM"
  • WSPR6 = 341,219 % 27 = 20 = "U"
  • WSPR5 = 12,637 % 26 = 1 = "B"
  • WSPR4 = 486 % 26 = 18 = ""S"
  • WSPR2 = 18 = "S"
    • Assuming we chose our hard=coded ID characters as "0" and "9"
    • Assuming Grid is FN12
    • WSPR string:
      • 0S9SBU  FN12  17
Checking our work
  • Decoding the WSPR
    • Starting value:  0S9SBU  FN12  17
      • Pico ID:  09
      • Grid: FN12
    • WSPR2 = "S" = 18;   num = 18
    • WSPR4 = "S" = 18; num = 18 * 26 + 18 = 486
    • WSPR5 = "B" = 1; num = 486 * 26 + 1 = 12,637
    • WSPR6 = "U" = 20; num = 12,637 * 27 + 20 = 341,219
    • DBM = "17" = 5; num = 341,219 * 19 + 5 = 6,483,166
  • Converting to telemetry
    • 6,483,166  % 10 = 6; num = 6,483,166 /10;  Sats = 6 (6 sats)
    • 648,316 % 7 = 4; num = 648,316 / 7;  Solar = 4 (0.8v)
    • 92,616 % 9 = 6; num = 92,616 / 9; Lipo = 6 (4.4v)
    • 10,290 % 11 = 5; num = num / 11; Temp = 5 (-20c)
    • 935 % 3 = 2; num = num / 3;  Alt Granular = 2 (666m)
    • 311% 24 = 23; num = num / 24; Grid6 = 23 = "X"
    • 12; Grid 5 = 12 = "M"
Caveats
  • Any temperature warmer than 10c, will be sent as 10c.
  • Any temperature colder than -45c will be sent as -45c.
  • Battery and Solar voltages are assuming LiPo battery, and solar cells wired in parallel, not series, to keep the voltage low.
  • Satellites of "0" will mean NO GPS lock.  Satellites of 9 will represent 9 or more.

Differences from VE3KCL's scheme
  • The Grid locator is not overlayed, so that the map view on wsprnet.org will show telemetry beside the balloon.
  • I use the option of a space in the 6th character of the callsign to squeeze a little more data in.
  • I encode altitude data in the first WSPR packet.
  • I encode data differently in the second packet.
Next steps

I'd like a few fellow pico/WSPR folks to review this document and provide feedback.