mc-Things

mc-Products => mc-Product General => Topic started by: Nick_W on September 02, 2016, 05:10:21 pm

Title: Where I'm keeping my Code
Post by: Nick_W on September 02, 2016, 05:10:21 pm
Until we have the Github site here figure out (and maybe even after that), all my stuff is located at:
https://github.com/NickWaterton (https://github.com/NickWaterton)

The structure is not great, and things that are there and have the same name as on the mcThings GitHub site are probably NOT the same. I have changed a lot of stuff (examples too) and re-written some of the libraries (the accelerator library for instance is re-written).

Feel free to use it, no guarantees that there aren't any bugs, it's all a work in progress.  ;D
Title: Re: Where I'm keeping my Code
Post by: plains203 on September 02, 2016, 06:56:39 pm
Thanks for sharing your code. I am sure to find some useful ideas in there.
Title: Re: Where I'm keeping my Code
Post by: kbrooking on September 09, 2016, 09:54:23 pm
Thanks Nick. Much appreciated. Lots of good stuff here to get newbies started.

One question. The "Class to utilize MMA8652 Accelerometer" is this the accelerometer that comes on the Mod120 or is this an external sensor you added?
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 09, 2016, 10:37:44 pm
This is the on board accelerometer, no other hardware required (I'm using 110 modules, but I think the 120 accelerometer is the same).

I mostly added utility functions, plus re-did the transient and orientation configuration routines to make them more readable (and work better!).

I added a bunch of Constants so that you can use meaningful names in place of magic numbers. Mostly shamelessly stolen from other Aduino libraries.

There is a lot more work to do on it, but it's a start.
Title: Re: Where I'm keeping my Code
Post by: kbrooking on September 09, 2016, 10:49:44 pm
Hmmm... That's interesting. So you can reuse other folks Aduino code samples on these devices as well, is that correct?
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 09, 2016, 11:09:02 pm
Not as is. The Arduino libraries are written in C (or C++), so you have to rewrite them into the modules language, which is vb.net "like".

I don't know vb.net, but it's not too difficult, however I do know C (and C++), so it's not hard to translate one to the other, assuming you can figure out what the C library is doing. Just time consuming...

Now if the modules language just had unsigned integers, and a long data type, and a millis equivalent... It would be so much easier. Still, it does have a String type, which C still doesn't.

It's almost as bad as trying to write Java! (but no, nothing is that bad).
Title: Re: Where I'm keeping my Code
Post by: kbrooking on September 17, 2016, 07:00:24 pm
Hello Nick,

Iím looking over your DoorSensor code and is very interesting. A lot here a newbie could learn from.

I know itís a lot to ask but, would it be possible for you to do an article stepping us through your code?

 I know I, as well as others in the community could really benefit from this. ;D
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 17, 2016, 07:04:26 pm
I can put something together, most of it is simple bit wise masking, as with this accelerometer, everything is set via bits.

I'll post when I have something.
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 18, 2016, 11:31:16 am
I will post in small (digestible) chunks.

First, to understand the code, you need to understand the mma8652fc - you can read the data sheet (DS in the code references) but it can be hard to understand. Here is the condensed version.

The mma8652 works in two ways:
1) X,Y,Z acceleration (including gravity) are continually measured at the  Output Data Rate (ODR), which can be configured to be between 1.56 to 800 Hz. These values are read from the OUT registers, and can be configured to have a range of 0 to (+-)2,4, or 8 g. New reading available is indicated by the STATUS register, but you can ignore this and just read the OUT registers, which will reset the STATUS register. The higher the frequency of readings, the more power is used.

2) Events can be detected, and trigger interrupts. The interrupts can be INT 1 or 2 and correspond to the MCThings accelerator interrupt 1 or 2. Events can be: Motion, Tap (pulse), Transient, Freefall, Orientation.

There are two settings, Active and Standby. You can read registers in Active or Standby mode, but you can only write (configure) registers in Standby mode. The system only takes readings in Active mode. So to configure the system, you switch to Standby, configure, then switch to Active mode.

There are two modes, Wake and Sleep. In wake mode, the system runs at the wake ODR (up to 800 Hz), in sleep mode the system runs at the sleep ODR (up to 50Hz).
The idea is that you run at a low ODR in sleep mode, to save power, then when an event triggers, the system wakes and switches to the wake ODR. After a configurable period, the system switches back to sleep mode. You can trigger the transition manually, or even disable sleep mode, but using the MCThings modules, it makes most sense to have it set up to switch from sleep to wake mode and back automatically.

The thing to realize about the ODR is that at a low ODR (1.56 Hz), there is 680ms between readings, so if you want to detect a transient or tap of duration 50ms, this won't work. You would need an ODR which has a sample rate of less than 50ms (if you care, google Nyquist sampling). 50Hz is 20ms per reading, so that would detect a 50ms duration event. An event like Landscape/Portrate switch obviously has a long duration, so 680ms detection rate would work perfectly well. Some experimentation with ODR is required if you are trying to detect short duration events (taps, thumps, rapid changes etc).

There are 5 configuration registers CTL_REG1 to 5. These are what are used for the basic set up, then each event has its own set of registers that set things specific to that event (threshold, angles, duration of event to trigger etc).

CTL_REG1 sets wake and sleep frequency, plus Active/Standby mode.
CTL_REG2 sets sleep/wake configuration (enable sleep, hi-res vs low-power etc)
CTL_REG3 sets the events to use to switch from sleep to wake mode, plus interrupt mode.
CTR_REG4 sets the events to cause an interrupt (note this is different from just switching from sleep mode)
CTL_REG5 sets which INT to activate (1 or 2) for each event.

When an interrupt is generated, you then have to read the INT_SOURCE register, to find out what the source of the interrupt was. Ie if INT1 is triggered, you don't know what triggered it (you can assign anything to either interrupt), so you read INT_SOURCE, and the bits that are set tells you what generated the interrupt.

Once you know what generated the interrupt, if you want more data (like magnitude, angle etc) you read the status register for that event. Reading the status register also clears the interrupt in the INT_SOURCE register, reading INT_SOURCE does not clear INT_SOURCE.

So for example, if you configured the orientation interrupt, to detect Portrate/Landscape change (called PL in the code/Data Sheet), then when an event triggers, you read INT_SOURCE, find that it's the PL interrupt, then read the PL_STATUS register to get details (such as portrate or landscape orientation), which resets the INT_SOURCE PL bit.

Now we know what we are trying to do, the next post will explain the code that does it.
Title: Re: Where I'm keeping my Code
Post by: kbrooking on September 18, 2016, 12:16:41 pm
Thanks Nick. Good information here but, Iím a bit confused.

Are we responsible for instructing mma8652fc which specific events we want to detect (via the CTR_REG4 while in Standby mode) or is the mma8652fc always monitoring these events and triggering the interrupts automatically?
Title: Re: Where I'm keeping my Code
Post by: kbrooking on September 18, 2016, 08:05:14 pm
Hello Nick,

In the below code snippet from the MMA8652 library, the whoAmI() function call is returning 0x00 and so the Accelerometer is never enabled.
Any suggestions as to why it is not returning 0x4a?

Public Sub New()
        gAccelerometer = I2c.Create(I2C_SPEED, Pin.SCL, Pin.SDA, I2C_ADDR)
        If whoAmI() = 0x4a Then
            online = True
            reset()
            // Set interrupt active low
            write(CTRL_REG3, read(CTRL_REG3) & ~IPOL_MASK) // clear bit 1 (active low)
            // Set interrupt push/pull
            write(CTRL_REG3, read(CTRL_REG3) & ~PP_OD_MASK) // clear bit 0 (push-pull)
        End If
    End Sub
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 19, 2016, 09:31:34 am
Quote
Are we responsible for instructing mma8652fc which specific events we want to detect (via the CTR_REG4 while in Standby mode) or is the mma8652fc always monitoring these events and triggering the interrupts automatically?

The answer is yes, you have to specifically enable which interrupts you want the MMA8652 to generate, it does not generate any by default. You also have to configure parameters specific to that event. For some, the default values will work, but others (say threshold), you would need to set explicity.

You then have to switch to Active() mode, to start the MMA8652 running.

Also note the interrupts do not fire in sleep mode, the device has to wake from sleep, then trigger the interrupt, so you have to set the same event to trigger wake from sleep in CTR_REG3 (assuming you have enabled sleep mode).
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 19, 2016, 09:54:24 am
Quote
In the below code snippet from the MMA8652 library, the whoAmI() function call is returning 0x00 and so the Accelerometer is never enabled.
Any suggestions as to why it is not returning 0x4a?

It works fine for me. I have just loaded the code into a new 110 module running 7.370 F/W

Here is the MQTT output

Code: [Select]
MCThings/000111B4/Status Booted: V1.02
MCThings/000111B4/Status Accel Sensor Online
MCThings/000111B4/KnockEnable True
MCThings/000111B4/Status OnLine

In order to read/write the I2C to the module, the read and write routines in the library are very specific. The MMA8562 needs a "repeated start" before you can read it. It is possible that I have a bug in here, as I'm not sure how to do a "repeated start", with the code tools we have. I do a write (without a stop) then a read - which is required for a repeated start - ie you can't have a stop before a read.

Can you post your code somewhere (I appreciate it's probably quite long) so that I can try it, or download from my github again? I did fix some small typo's in the last day or so. Not that they should effect anything, but it's working as is on my two 110 test modules.

If you put a magnet against the reedswitch, wait 5 seconds, then tap the module several times quickly (like a knock...), this is what you should see:

Quote
MCThings/000111B4/Door False
MCThings/000111B4/Doorknock True

Door False is the door detected as closed.
Doorknock True is what you get when two taps less than 0.75 seconds apart are detected (and the door remains closed for more than 1 second afterward).
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 19, 2016, 10:47:09 am
Here is my test set up (note the magnet), and the actual installation (top left hand corner of door).



Title: Re: Where I'm keeping my Code
Post by: kbrooking on September 19, 2016, 03:08:33 pm
Hello Nick,

I'm using the 120 modules. Could that be the reason?
Title: Re: Where I'm keeping my Code
Post by: mc-John on September 19, 2016, 06:03:24 pm
Quote
I'm using the 120 modules. Could that be the reason?

Yes, the mc-Mod120 has a much more advantaged but different accelerometer.
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 19, 2016, 08:01:28 pm
That could be it, maybe there is something different about the 120.

I have a couple on order, but don't have them yet. I'll look into it.

Edit. Oops! Didn't see the above post before I replied...
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 19, 2016, 08:26:40 pm
Ok,

The 120 module uses a completely different accelerometer. It's an ST LIS2DH12, which has a different I2C address (0x19), and while it has similar registers to the MMA8652, they are not the same, or the same addresses either.

I will need to rewrite the library completely for the new modules (sigh).

The good news is that it is a much lower power device, and has a thermometer on board (so now you have two, or three if you count die temp).

The 120 module seems to be lower power overall, so battery life should be better than the 110 modules.

I need to check where my modules are, and see what is needed for the new library....
Title: Re: Where I'm keeping my Code
Post by: Nick_W on September 19, 2016, 08:50:20 pm
Reading the data sheet of the new accelerometer, I would not try changing the I2C address or anything, this is from the data sheet:
Quote
Registers marked as Reserved or not listed in the table above must not be changed. Writing to those registers may cause permanent damage to the device

Tread carefully!
Title: Re: Where I'm keeping my Code
Post by: kbrooking on September 20, 2016, 09:16:44 pm
Thanks Nick,

I also noticed that the link to the data sheet is broken. If you need any help with the library let know what I can do.
Title: Re: Where I'm keeping my Code
Post by: mc-T2 on September 21, 2016, 10:27:41 am
Hey guys,
we fixed the data sheet link and are updating that on the website today. Thanks for pointing that out!