-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement error detection / correction #32
Comments
Big fan of WebJack! Been playing with it a lot, so many interesting projects to be done with it! One basic use-case I have is simply receiving sensor data in the browser from an Arduino. I've been playing around with that, and it seems that (with my shaky circuit setup, which can be improved), I often find a lot of '3's sent by the Arduino are parsed as '7's by Webjack. One very simple (not so efficient) form of error correction I just came upon is a type of Forward Error Correction (FEC), in which one simply transmits each bit 3 times, and then the receiver does a 'majority vote' on the bits received. I'm thinking of implementing this in a really crude way in WebJack, but I'd be curious as to how you think it might be best implemented? The nice thing about this (for my application at least) is that I don't need to worry about two-way communication, and it seems quite simple conceptually. In searching for error correction techniques with modems, I happened across this project, which looks like it has implemented some acknowlege / receive stuff, and perhaps some error correction ... maybe an inspiration? https://cho45.stfuawsc.com/WebAudio-Modem/FSK/modem.html Anyway, thanks for all your great work! Cheers, |
Don - found this library, not sure if it's done, and we'd want to add some tests of some kind: https://github.com/sergiopantoja/Hamming.js/ Explanation of Hamming codes which seems pretty cool: https://en.wikipedia.org/wiki/Hamming_code It doesn't look complete, though -- it returns an object which has a |
Other implementations of Hamming and something called Manchester encoding: https://gist.github.com/joeladdison/9717310 Also a very short example here: https://gist.github.com/ivanpepelko/b4c290f4645865f8fec581016a96420e But |
My thought on the webjack integration would be: Webjack accepts a constructor option in the passed var profile = WebJack.Profiles.SoftModem;
profile.sendFilter = function(output) {
return output; // this is the default -- no error correction on send
}
profile.receiveFilter = function(input) {
return input; // this is the default -- only raw data expected
}
profile.sendFilter = function(input) {
return hamming.generate(input); // or, override it like this
}
var connection = new WebJack.Connection(profile); |
Cool! Yes, seems that Hamming not only detects, but can correct errors! The downside of Hamming (if I'm reading things right) is that it would, in fact, require interventions at the "bit" level of communication -- e.g. Hamming 7,4 requires adding 3 additional "parity" bits for every 4 bits you send. I think this would require a rewrite of how SoftModem and WebJack work. |
But couldn't we transmit the bits as strings or something? Just jump a On Sep 25, 2016 6:20 PM, "dwblair" [email protected] wrote: Cool! Yes, seems that Hamming not only detects, but can correct errors! The downside of Hamming (if I'm reading things right) is that it would, in — Reply to this email directly, view it on GitHub |
I think we could do that -- e.g., for Hamming 7,4 (which requires 3 additional 'parity' bits for every 4 bits of data you want to send), if you want to send an ascii "8", you first break it down into bits: (in this case, "00111000") then break it down into groups of 4 bits (e.g. "0011", "1000"), and determine the proper additional 3 parity bits to send along with each of those 4 bits ... so then, instead of sending "8", or just its binary representation "00111000", you send the Hamming 7,4 representation "0011abc1000def" (where a,b,c,d,e,f are the appropriate Hamming parity bits (each of them a "0" or a "1")), and then reconstruct on the other side using the appropriate inverse Hamming method, yeah? I think the downside of abstracting things at this level might be (if I'm doing the arithmetic right) that for every character you want to send across the line (e.g. "8"), you now would need to send 14 characters ("00110101000101", or whatever Hamming 7,4 would generate). Currently, I'm able to send data to WebJack about every 200 ms -- so something like 5 values per second, which is fairly snappy; shorter delays than 200 ms, and I start to see a lot of errors. Naively, I think this high-level Hamming (HLH?) approach would bring that delay up to about 14*200 ms -- i.e., or once every 3 seconds (maybe a little faster b/c of the error-correction due to Hamming, but not much -- if I understand Hamming 7,4 right, I think if more than 2 out of every 7 bits are flipped, Hamming 7,4 is no longer effective.) The upside would be that we'd be fairly sure we got every data point; once every 3 seconds is certainly fast enough for some applications. For the sorts of things I'm thinking of doing, though -- playing 'live' with thermistors and loadcells and photocells and watching their response in the browser -- maybe even sending chat messages from browser to browser -- 1 character per 3 seconds a bit too sluggish. If I were going to implement Hamming, I think we'd want to do it at the bit level, to make it faster than this. Which might be a good project to take up! It would certainly make SoftModem and WebJack more robust to have error-correction at the bit level. At this point, for a quick-and-dirty (and, apparently, commonly employed) solution, I'm headed down the route of using CRC codes, which are widely used in radio and in internet protocols. They're relatively simple, and they only add a fixed length checksum to the transmission of any arbitrary-length string -- in the case of CRC8, a single byte. It's only an "error detection", not an "error correction", code, but I was anyway finding that the error rates were fairly low; and for most of the things I'm interested in, a few dropped data points don't matter too much; I'd rather have a snappy response time. Also: if there's two-way communication, and one wants to make sure not to lose any packets, the typical thing that's done is to just ask for a re-send if the checksum doesn't match. That's quite with the current WebJack setup, I think. I hunted / fiddled around a bunch this morning, and now have compatible javascript and arduino functions ( "CRC8()") for generating a CRC8 checksum, which is simply a single byte.: https://github.com/dwblair/crc8-avr-js So, my plan at this point is: on the arduino side, use CRC8() to generate a checksum for a given message, and use SoftModem to send something like "message;checksum" to the browser ... ... then, on the browser side, read in "message%checksum", leverage the "%" character (or whatever would make for a good separating character) to split message and checksum apart; use CRC8() on the browser side to generate the checksum for message independently, and compare that checksum to the one you received from the Arduino. If they differ, then you ask for a re-send (or, if you don't care too much about every data point, you just don't keep that message ... but maybe you tally up an "error counter" so you have a sense for how bad the connection is) ... |
Implemented CRC8! Sorry the video is blurry ... but basically it shows:
you can see a "noise" event detected at https://youtu.be/7RDXzkhKuZY?t=22 i'll clean up the code and see if i can find a way to do a PR that doesn't break things now i used it for graphing thermistor data, and it was super smooth -- no glitches! I tried hard resetting my repo as before to get rid of merge conflicts, but there still seems to be a conflict with the README even after I do that ... so still learning :) Meanwhile, for what it's worth -- the code is still messy, but i pulled out the new example folders into a separate repo here: https://github.com/dwblair/webjack-crc8 I'll be refactoring in the next day or so and trying to figure out how to do a nice PR against the main repo ... |
Hi, Don -- fantastic! You can follow these steps:
Does this make sense? I hope I didn't forget anything! |
Ah -- the README conflict is because I merged in a change to the README from Richard -- so you need to resolve that conflict before switching back to master, in step 2 (or maybe 1). He fixed the spacing in one of the tables. |
Wow, thank you for outlining all these steps! I'm going to dig in and On Mon, Sep 26, 2016 at 9:35 AM, Jeffrey Warren [email protected]
|
This would be great for increased transmission quality, especially for the browser-to-browser use case.
https://en.wikipedia.org/wiki/Error_detection_and_correction
For both, detection and correction, it always needs sending addtional bits. The question is where to place the redundant bits. Currently, SoftModem sends data like UART but without parity bit: one frame is one byte.
Some possible options:
Resource for CRC hashes on the Arduino:
http://excamera.com/sphinx/article-crc.html
Related node packages:
https://github.com/pbrandt1/FEC
https://github.com/quiet/libfec
https://github.com/jorangreef/reed-solomon
Another good article about error detection and correction:
https://hackaday.com/2016/02/10/error-detection-and-correction-reed-solomon-convolution-and-trellis-diagrams/#more-189519
Detection vs. Correction:
I'd say in this case correction is the better option, as detection would require resending, which is not provided by librarys like Firmata.
The text was updated successfully, but these errors were encountered: