Transmit arbitrary data at a set baud rate (1.2kHz)

Posted on
  • I've got a project that requires communicating with a message bus via Manchester encoding at 1.2kHz.

    Essentially this means I need to be able to accurately create pulses of low -> high or high -> low voltage lasting ~417 micoseconds each. (so the total low to high or high to low cycle is 813microseconds)

    I've tried chaining digitalPulse() calls - but hit a few stumbling blocks, in particular the fact that two consecutive '1' pulses will be separated by a short '0' voltage.

    I then looked at setInterval() in conjunction with a function calling digitalWrite() which seemed good down to about 0.5ms (so nearly but not quite the accuracy I need.)

    UART I don't think will work because of the start and stop bits (not needed in my implementation), and then I did start to look at using SPI.send8bit() / SPI.send4bit() just over 1 wire, but either that simply has no chance of working because there's no clock connected or else I couldn't seem to slow the baud rate down sufficiently.

    Any other suggestions out there I might try before I have to resort to embedded C (i.e. arduino) and give up on the arduino / javascript route?

  • Shame about digitalPulse... That would have been ideal. I'll take a look next week and see if there's anything I can do in Espruino - but for now you could just ensure that in your code you never do two consecutive dugitalPulse(1), and instead create a single digital pulse with twice the length? That shouldn't be too trickly?

    The other option is actually to use Waveform to output what you need. While it is meant for analog it could also be used for digital if you just used 0 and 255...

  • Good idea - I'll give waveform a go.

    I'm finding that as soon as I put more than a couple of lines of logic around the digitalPulses then it starts to throw the timings out, but perhaps I could construct the message payload in advance into an array of functions, and then simply iterate the array and call each function in sequence - that might be worth a try?

    I started looking into the espruino code last night, wondering how hard or otherwise it would be to create a new function based on the digital pulse and / or serial code to encode and transmit a byte array in manchester at a specific baud rate.

    I'm thinking I'd need something like a jswrap_io_manchesterWrite(Pin, byte, baudRate) function in src/jswrap_io.c, then presumably some code in targets/.../jshardware.cpp - Would I need to implement this for mbed, arduino and linux targets as well as stm32?

    I've also not yet worked out how the javascript is translated into the c++ function calls. Am I anywhere near the right track here or should I leave that kind of stuff to the professionals :-) ?

  • Tried analogWrite() in sequence - but I can't seem to get a consistent reading on my oscilloscope. I'm guessing this is because it's an async function call, and so doesn't wait for one call to finish before executing the next (which was why digitalPulse was so appealing), so I'd be back to using timeout between calls for analogWrite() which then loses the microsecond accuracy.

  • Have you tried what's suggested here?
    I'm not sure repeated analog writes will help, but the Waveform class will probably work well.

    For the moment I'd use one of the DAC pins (A4 or A5) as the PWM pins could maybe cause problems with when they update.

    It could be that the JS execution speed is what's throwing the digitalPulse out... If you try creating a new Uint8Array(bits) and then pre-calculating the high and low periods as you say, that will probably work fine too.

    But yes, if you did want to do a manchester encoding function, making jswrap_io_manchesterWrite function is how you'd go about it. The specially formatted comments above each function are parsed during the build process, and then used to automatically make the function callable from JavaScript.

    However I wouldn't go as far as adding something to jshardware. When called from native code, I reckon that jshPinOutputAtTime as used by digitalPulse (if I remember right) will be more than fast enough for what you need.

    Personally I'd give standard JavaScript digitalPulse another try with the precalculated array though. Something like this should push out the pulses very fast once you've calculated them:

    var pulses = new Uint8Array(...);
    pulses.forEach(function(period,idx) {digitalPulse(pin, idx&1, 1234*period);});
  • Thanks again for all your help - I think the digitalPulse may well work, but if not I'll look at the waveform in more detail.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Transmit arbitrary data at a set baud rate (1.2kHz)

Posted by Avatar for GoIncremental @GoIncremental