You should soon be able to see me on APRS as either MM6HCK-5 (via APRS-IS) or MM6HCK-7 (via 2m AFSK).

Tuesday, 16 December 2014

Saturday, 13 December 2014

TicketGET. Let the fun begin!

I've been notably absent for a few weeksmonths. In case you were wondering, this is why...

So now, I can transmit on a much, much wider range of frequencies (but still not broadcast FM :))

My prime reasons for getting it was thus:
  • RTL SDR sticks are nice and all, but I want more capabilities, namely to transmit.
  • This is why this package is on its way...
  • I am literally drowning in Baofeng handies at the moment, it would be nice to use them.
  • It means I have an excuse to put up a giant f*cking dipole like the ZS6BKW.
 Assembly of the PSDR1... well, the opamps, balun and DDS are on the board, but I just haven't had the time (or the components) to assemble the rest. I'll get round to it eventually. Although, that's what I said about this blog...

Thursday, 14 August 2014

PSDR1 Virgin board has arrived....

...and it's frickin' tiny! A little bigger than a RasPi.

In case you're unfamiliar with this project, look here.

I'll be posting more pics as the build progresses...

Friday, 25 July 2014

The "Hornet": Simple medium-power experimental FM transmitter with common parts

There has been a proliferation of FM "bugs" across the usual suspects of late, all based on rather similar designs, using common components. Wild promises are made about the range and stability of these things, like a few hundred metres. I built a few of them and only one even managed to penetrate a wall, let alone get a few hundred metres.

So, I did what any self respecting hacker would do... and improved it.

  • This circuit is almost certainly illegal to operate in your jurisdiction without an FM broadcast license due to its output power and signal characteristics. 
  • This circuit is provided for educational purposes only and I take no responsibility for interference caused by your build.
  • You should not attempt to build this unless you have some RF experience. 
  • Do not touch the antenna or LC tank (C3/L1) while the circuit is powered. 
  • Do NOT operate this circuit within 10 mi of an airport, unless you know what you are doing! There is no compressor and therefore overdriving the input (eg driving it from a computer line level output at full volume) may cause the signal to spill over into the Airband. This circuit has more than enough power to reach airplanes on approach to an airport and penalties for interference can be severe.

So this design is based on the Talking Electronics "Wasp" with a few important modifications.

The Wasp uses the same three small-signal, low-power transistors. They have an fT (transition frequency) of about 300MHz so can work in all manner of bands, but they cannot switch much current and hence the output power is in the range of a couple of milliwatts. The Wasp will put out probably 20-25mW - that's being generous.

However, the final transistor (Q3) in this circuit is the common BD139 NPN medium-power transistor common in ham QRP equipment. These are pence and are in pretty much every well stocked junk box or parts drawer. The 2SD882 is an even better choice but unless you're in Asia they are a bloody nightmare to obtain.

Now, I don't have access to an RF wattmeter right this second, but at a distance of 1.6 miles (2.5km) an RTL-SDR was still showing ~-30dB with crystal clear audio, with a hill and a housing estate in the way. Extrapolating from previous experiments this suggests an output power of at least half a watt if not quite a bit more.

The compromise is a lower (but still impressive for an audio transistor!) fT of about 90MHz, above which, the acheivable gain starts to drop off rapidly. Below that, though, well, impressive stuff happens!

The BD139 is used as a Class A amplifier and also acts as a buffer, decoupling the antenna from the LC tank which was a major problem with the circuits linked at the start of this article (which are, at their most basic, just FM exciters); the direct coupling from LC tank to antenna caused nearby objects to chance the capacitance of the circuit as a whole and it would start to drift more than a Skyline with wheels made of butter.

This is another idea taken from the Wasp; with this arrangement it still drifts a little but nowhere near the "oh god where the hell has that carrier disappeared to now" levels of the exciter-only circuits. It's enough to shift the carrier off by a few kHz at most but this will still stay in the pass band of most tuned WFM recievers.

Whereas all these bugs use little electret microphones, I find they perform unsatisfactorily even with the gain turned all the way up, so I've just stuck on a line level input. To keep things simple I have chosen to downmix into mono; this part is actually optional and you can just use the ground and left channel as inputs and leave the right channel floating.

I chose a Diamond SRH-771 for the antenna because I have one to hand that recently broke on me. While it's not even nearly resonant at low VHF it does provide satisfactory performance. A "rabbit ears" dipole 1.5m long is best though, or if you're really going for it, why not a yagi? ;)

Please excuse the state of L1, this thing started out at 122MHz and have you ever tried to re-wind a coil soldered into a board?
Contrary to Colin's advice on the original, you can very much build this on matrix board and it will hum along quite happily.

I mounted mine in an old dead laptop PSU casing I had laying around, there is exactly enough space for the heatsink and the battery to hold each other in by friction. The antenna is superglued to the top, although I'll be modding the case to be a bit more slick when I get the chance.

The coil is five turns of .51mm enameled copper wire using an M5 bolt as the former, which I call the 555 rule (no relation): in combination with a 33nF ceramic NP0 capacitor (with a black top) this combo usually sits around 84-88MHz. My first build had 7 or 8 hence the higher frequency.

An NP0 cap isn't strictly necessary but the LC tank will drift less.

Anyway, as I test this more I will post results, but it's an exciting piece of kit to build; if you live in the middle of nowhere, and are daring enough, build it let me know how you get on!

Sunday, 6 July 2014

I made an amplifier.

Nothing special, just an LM386 according to the reference design, with one or two minor mods:

  • The VIN pot's value doesn't actually matter that much. It's a potential divider. All the value will affect is how much the volume will roll off. I stuck in a 4.7K linear pot and it's feeble but enough.
  • I can't stress this enough: check your grounds! I got a LOUD buzzing noise the first time I powered it up; transpired my input ground (hanging off the 10K pot in the schematic) had come loose. Oops.
  • This thing is noisy. Like, tube amp noisy.
  • That Pin 7 bypass cap is not optional. Well, it is, but it shouldn't be. If you omit it the 386 will motorboat (oscillate) like a washing machine with a bad brick habit.
  • The pot I have seems to be dying a slow death, not only is it stiff, but there seems to be a short in there somewhere, because the op amp starts slamming into the rails with quite some force - acting as a voltage comparator instead of an amplifier - if you so much as knock the pot a little bit. I think I lost high frequency hearing in one ear and a heaphone driver finding this out...
  • I added a series RC filter between 1 and 5 for bass boost; I didn't have a .033uF capacitor to hand - of course, TI had to choose the one value I didn't have - but I did have a .047uF polyester cap, which seemed to work just as well. Doing the math it will push the bass boost down from 190Hz to around 140Hz (frequency decreases as capacitance increases) but that's not a problem for me.

    These are the values I used for the lowpass:

So why the sudden interest in audio op amps? I'll eventually get round to building a PixieII to supplement my growing collection of homebrew QRP transceivers. (Which currently stands at one. :]) On top of that I managed to salvage a speaker from an old TV which will be sent to a WEEE guy soon (who will be bewildered as hell to find half the board desoldered and lacking of RF components...)

(I'll post a pic of the finished project as soon as I get the camera back...)

Oh and finally, the eagle eyed among you will notice the change in design - I was getting sick of grey and orange, so I've gone for something a bit more minimal. Hope you like!

Sunday, 29 June 2014

SPI (mis-)Adventures: Probing the LIS302DL 3 Axis Accelerometer

The Effing Datasheet

Some stuff about the LIS3xxDL

Image courtesy WejP, source here.

I said I'd get around to doing SPI on this thing, so here it is. This blog seems to be gaining viewership and interest so for once I'm actually going to continue posting, hah :)

The STM32F407 Discovery board contains an on board ST LIS302DL 3-axis MEMS accelerometer. MEMS technology - short for microelectromechanical sensor (try saying that when you're drunk)- is a pretty cool application of physics. You see, tiny (a few μm in size) metallic plates are placed a few
μm apart, and changes in capacitance caused by their movement are read by a tiny ADC and digitised, allowing a wide range of sensors that have traditionally been rather unwieldy to place on a small board to be shrunk down to a few millimetres across.

The board also contains a MEMS microphone that operates on the same principle, although its output is digital PDM (pulse duration modulation) which currently I have no clue how to decode. Whereas a traditional electret mic is a cm or so across and a good 5mm deep, the MEMS mic on the board is 3x4x1mm. You could fit four on a little fingernail with room to spare!

Trivia moment: The LIS301DL was the accelerometer in the original iPhone and still features in a number of Android smartphones, if the name seems familiar.

The device is accessed over a serial peripheral interface bus, and ChibiOS comes specifically with a library for accessing the LIS302DL on the Discovery board.

But, I'm learning SPI on the STM32 in general, so where's the fun in using a black box library to access hardware I could very well poke at myself? Balls to that. :)

Looking at the LIS302DL library & MEMS example that comes with ChibiOS, it seems the following things happen:
  • SPI is initialised, and SPI1 selected.
    SPI1 is the SPI channel that the accelerometer is on. Remember that SPI devices can be daisychained and that only one extra wire (for Chip Select) is needed for each SPI slave; all the SCLK/MISO/MOSI lines can be tied together. That's a subject for a future post, though.
  • The LIS302DL is initialised.
    We can see from the MEMS example that 0x43, 0x0, 0x0 are written to registers 0x20, 0x21 and 0x21 (the LIS302DL's control registers). Looking at the datasheet, 0x43 (0b01000011) in the first control register corresponds to:
    • Bit 1: Data rate (0 = 100Hz)
    • Bit 2: Power down (1 = Off)
    • Bit 3: Full Scale (0 = default)
    • Bits 4 & 5: Self Test Mode (0 = off/normal)
    • Bit 6, 7 and 8: Z, Y and X channels enabled (011 = Y and X only).
  • (As an aside, 0x73 is probably a better choice for us - 0b01000111 - since this enables the Z axis as well.)
    We don't use interrupts in our application so we can leave CTRL_REG2 and CTRL_REG3 alone.
  • We read out the values.These are stored in registers 0x29, 0x2B and 0x2D.
Looking at this from an SPI point of view, the chip accepts two bytes over the MOSI line, and feeds back two bytes over MISO. The first byte in each case is the register in question with the second being the data; we can read out a register by passing 0x80 with the register as byte 2.

Also note that the example deasserts /CS (spiUnselect(&SPID1);) after each transaction. This is important, otherwise the chip's SPI interface will think any further bytes are a continuation of the first command and you will get back 0xFFFF from the chip (which I'm presuming is an error state).

I have posted the menu module here, to demonstrate how to read out values from the accelerometer.

Much of it should be pretty damn obvious; you should ensure SPI is enabled in the HAL and ChibiOS config headers within your project directory.

One thing not immediately intuitive is the control register values in the SPIConfig struct. Fear not, young padawan, for on page 901 of the monster that is The Bible of STM32F4, also known as RM0090: STM32F4xx Reference Manual, lists all the possible values we can put in SPI_CR1. These can be OR'd together, and are explained in further detail in said document. The interesting ones, if we're using 3-wire SPI like any sane human being, are:
    Set if least significant bit is transmitted first; otherwise, MSB is first (which is the case with a majority of SPI-interfaced chips.)
  • SPI_CR1_BRn (where n is 0, 1, 2)
    Set bit rate as a fraction of the peripheral clock rate (fPCLK), with 000 being the fastest and 111 being the slowest. You will generally find the maximum speed in the slave device's datasheet; alternatively, start at 111 and decrease by 1 (you do know how to count in binary, right?) until things stop working. :)
    SPI clock polarity and phase. The datasheet of the slave device will tell you which you need to use, sometimes devices (such as the AMIC 24L040 EEPROM) behave differently depending on clock phase and polarity.
 Another quick note that I should make is that you would usually put the spiStart function in main() and the SPIConfig as a static const SPIConfig cfg in the global scope, but I wanted to keep everything in one place for the sake of this post. It all seems to work fine, though. If SPI is enabled in the HAL config, I believe spiStart is automatically called when the HAL is initialised. But don't take my word for it.

So now you should have enough information to start poking at SPI devices for yourself. I'm not going to worry too much about the mic, because I intend to use the ADC to read an analog microphone anyway, but next I intend to figure out how DMA works on this chip, since polled SPI is going to be slowww with the ADC I intend to use.

Saturday, 28 June 2014

USB CDC, The ChibiOS Prompt, and the FPU

Three topics in one post! Aren't you a lucky reader? :)

USB Serial, or Why The USB-IF Deserves a Special Place in Hell

If you're used to simple TTL/RS232 serial, USB is a whole different ballgame. Here's the thing; it was not designed to be an easy bus protocol to program with. With all that flexibility, and the user-shalt-not-configure interface, comes a heap load more complexity:

  • Connect wires.
  • Set baud rate.
  • Set databits.
  • Set parity.
  • Set stop bits.
  • Write a byte to/read a byte from a register. BOOM. Done.
  • Figure out how many endpoints you need.
    • Generally, one each for interrupt in/out, one each for bulk in/out.
  • Create the endpoint descriptors.
  • Create the configuration descriptors (includes VID:PID pair, manafacturer, product name, configuration, sub-interfaces, etc.)
  • Configure endpoint callbacks for send, receive, reset, probing, suspend, wakeup, stalling, etc.
  • Set up interrupts.
  • Cycle the bus (disconnect, wait, reconnect).
  • Pray it shows up.
  • On the host:
  • Enumerate all the USB devices.
  • Claim the one you want to communicate with.
  • Repeat steps 1-5.
and if you're lucky, you might have a connection to a device.

Dear lord. Suffice to say, you don't want to deal with this stuff yourself if you have never programmed USB before. Besides some experiments with LUFA, I haven't.

But I still wanted to cut the Arduino out of the development setup, because I wanted it as an SPI slave for future experiments, and it's just another piece of kit to lug around otherwise.

So since I'm using ChibiOS for the moment, I decided to simply strip the ARMCM4-STM32F407-DISCOVERY-MEMS demo of all the crap (stuff to do with the accelerometer, PWM, and so on) and simply reduce it down to the USB Serial initialisation and menu stuff.

See, that demo comes with a cute little prompt, from which you can build on and run experiments:

I don't think I even need to provide example code for this one; all you need to do is write an appropriate callback function with the prototype

static void cmd_your_callback_function_here(BaseSequentialStream *chp, int argc, char **argv)

   //and your code goes here!

and add it to the commands table:

static const ShellCommand commands[] = {
  {"mem", cmd_mem},
  {"threads", cmd_threads},
  {"test", cmd_test}, 

  {"your_command_here", cmd_your_callback_function_here},

Once you've done that, simply connect Minicom to the appropriate serial port (for me it's /dev/ttyACM0, or /dev/ttyACM1 if I have the Arduino attached), and hit Enter for the ch> prompt. help will list all the available commands:

There's not much more to it than that, really! test will run the inbuilt ChibiOS test suite and benchmark, info, mem, menuitem and led are demonstrated above (the led example toggles the given LED on Port D). threads shows the currently running threads (think processes on a Linux or Windows system) and systime will show the number of milliseconds since reset/power on.

What is hf, I hear you ask?

Part of the main attraction of these chips is their brilliant floating point support, something not many microcontrollers have. Since I'm going to be throwing around a lot of floating point numbers (complex numbers, FFT, square roots and such) the FPU is pretty much essential, and the STM32F4 series is pretty much the only ARM microcontroller line out there with hardware FPU/DSP support.

AVR and the like emulate FP numbers using fixed point representation, which I'm not going to go into here, but you can read up yourself.

hf (short for hardfloat, referring to the ARM VFP) simply runs a series of tests on the floating point unit, such as a straight divide -- including division by zero, but I'll get to that in a minute -- and also calculates some arctangents and square roots (which also involve division behind the scenes).

Curiously, if I set the denominator to 0, I get

22/0 = 2147483647.83647

as the result. Is this a bug in the STM32 I wonder? I think I need to read up a bit more on how to get this thing to respond to fault conditions... but what I do know is that particular number is 0xFFFFFFFF.FFFFFFFF if interpreted as single-precision floating point.[edit: or -1 if interpreted as a signed integer. n00b mistake. :)]

Anyway, aside from trying to blow up the CPU and destroy the Universe, samples of the ADC and DDS are on their way, the DBMs haven't turned up after nearly a month, ST are dragging their feet a little on bare chips (not that I'm complaining, they're worth the wait) and board progress is slow.

All in good time!