Multiple Analog Inputs producing strange data

Hi,

I’m currently doing a project, which requires me to measure and plot (via cosm) temperature and light intensity.

I’m using an LM35CZ sensor for reading the temperature and a Photoresistor for reading the light intensity.

I believe all is good on the hardware side of things - everything should be wired OK.

Since the LM35CZ requires a supply voltage of 4V+, I had to power it directly from Vcc (5V) instead of the 3V3 from the board. I also connected the Vcc GND and the voltage regulator’s GND since it turned out that they weren’t connected - I’m using the SparkFun Imp breakout board, based on the April design.

Attaching a photo - I don’t know if you’ll be able to make everything out…

I’ve got the plotting side of the project going OK (as well as sending out emails via agents :). I can lend a hand if anyone’s having issues with getting either of those things going.

What’s really bugging me is that everything seems to work great one minute, but then the values go haywire for no apparent reason. For example, once the Photoresistor starts reading values close to 0, the Temp sensor starts reading insanely high values…

Is there any known issue with consecutively reading several analog inputs?

I even placed imp.sleep(0.1) after each of the measurements in order to minimize any kind of potential interference between the two ports. Before I put this in I was getting even stranger values from hardware.pinx.read().

I’ll paste a couple of the relative functions just in case:

function checkPRes() { local rawValue = hardware.pin1.read(); local pResValue = 1 - (rawValue / 65535.0); imp.sleep(0.1); return pResValue; }
function checkTemp() { local rawValue = hardware.pin2.read(); local gain = 3.3/65535; local tempVolts = rawValue*gain; local tempActual = tempVolts / 0.01; local tempActualRound = format("%.2f",tempActual); tempActualRound = tempActualRound.tofloat(); imp.sleep(0.1); return tempActualRound; }

(The format() and tofloat() bits in the checkTemp() function are a workaround to set the decimal places since I wasn’t able to find a math.round() or similar function in the Squirrel manual… Please, correct me if there’s an easier / better way to do this, even though it seems to work OK and I don’t think it’s the source of the problem)

And help would be greatly appreciated since I think I’m going crazy!

I’ve had a few cases where I thought I was going crazy too. It’s a different sort of programming than what we’re used to? The language and the hardware. Don’t worry it’ll all make sense in the end. Here’s what I did for rounding:

v=math.floor(v*100)/100.0;

The grounds are definitely connected on April, I have no idea how they could not be connected on the sparkfun board but don’t have one to hand to check…

What does a voltmeter say (eg) pin2 is when it’s reading strange values?

First off - thanks for the lightning-fast replies! :slight_smile: Nothing is more exciting than being able to share your thoughts and problems with a community such as this! THANK YOU!

@sbright33 - I’ve worked extensively with the Arduino platform, but a couple of concepts here are very different… I’m also finding the lack of an extensive Electric Imp-specific manual a hassle - I have to constantly check the Squirrel Reference Manual and then experiment how to work with a lot of the functions on the Imp. This is, of course, a process and I hope we’ll see better documentation as the platform matures.

The math.floor() idea is a cool workaround, as well! :slight_smile:

@Hugo - It took me quite a while to figure out exactly what was causing the issue and when… I always assumed that I was doing something wrong (which is not at all unlikely) and that it was a software issue, but it could very well hardware from what I’m currently seeing.

I’ll take a couple of readings tonight and post the results once I get home. I’ll also check the grounds once more for argument’s sake.

Also, is there any kind of internal overvoltage protection on the Imp pins? Since I’m currently working with 3V3 and 5V it would be good to know.

Thanks again! :slight_smile:

p.s.

Mon Apr 29 2013 08:05:36 GMT+0300 (EEST): imp restarted, reason: wifi error

Can anyone give any insights into this error? It seems to occur randomly several times throughout the day without any user interaction whatsoever… Could it be caused by the AP, which I’m using since I don’t seem to recall this happening at another location (another AP)?

Did you try it with a different power supply (other than the USB cable?). I wonder if the USB power has some current supply issues. Try 4 AA batteries (6 volts).

Hi,

Thanks for the reply!

As of now I’ve only tried powering the Imp from a computer and directly via an HTC USB charger with no apparent change in behaviour.

I’ll post the results after doing a couple of readings later tonight.

The imp is not 5v tolerant; if you are working with 5v signals you should clamp them first (eg a zener clamp).

The wifi error is an issue with the current release, the next one has many fixes to the Broadcom code and we’ve not seen it happen since. There’s also a bug whereby if it happens once, then the error isn’t cleared and you will see bogus reports after that point :slight_smile:

Hi,

Sorry for taking so long to post this, but I wanted to make absolutely sure that this issue is not caused by something I’m doing.

Here’s what I can confirm:
The analog inputs occasionally go haywire with hardware.pinx.read() returning values, which don’t correspond to the current voltage across pin x.

I’ve yet to determine the cause or the steps to reproduce this - it seems to occur when I add a new component to the mix, e.g. a new sensor on a previously unused pin.

I was even forced to add an imp.sleep(0.1) after any function, which requested hardware.pinx.read(), which seemed to cut back on the false values.

Sometimes this issue affects all ADC readings, sometimes it affects the readings on a particular pin.

I know this isn’t the most useful feedback, but getting to the root of this issue is proving to be somewhat of a challenge.

I’ll try and experiment further with this - I’m thinking of attaching several analog sensors to the Imp and reading each one sequentially and printing out the values without any other code just to make sure that reading multiple sensors is not what’s causing the issue.

I really love the Electric Imp platform - I believe that this is an entirely new concept on things and that this is a game changer for sure! I’m even thinking of using the Imp in a couple of my pet projects, but I need those ADC readings to be spot-on 100% of the time since I’ll be controlling delicate stuff and I can’t have my thermometer suddenly spiking to 100 C for no apparent reason…

I really hope someone has a clue about this, because this is practically the only thing keeping me from purchasing a couple more Imps and digging in deeper to the platform!

p.s. Is there a roadmap somewhere online where we can see what’s planned for future releases of the Imp firmware? I’m particulary interested in countinuing to execute/ executing the Imp code in the event of an Internet failure… From what I’ve seen everything stops executing / doesn’t execute in the event of a network outage, am I correct?

Can you post your actual schematic someplace for us to see?

I’ve given up using the SD card analog inputs due to the inherent noise. Digital and analog rails are tied together, grounds are tied together, and there is no provision for an external reference. The slightest spike on a digital rail will affect your analog readings. One possible solution I tried for noise free inputs, was using the sampler, oversample at a very high rate, then decimate/average. It works nicely, but you can only do this for one channel.

Also, bear in mind that the hardware is only 12 bits, but the software reads 16 bits, so to improve your numbers, right shift by 4.

If you really need precise, low-noise analog values, you’ll have to use an external ADC with it’s own power supply, reference etc. I posted an example a while ago demonstrating a 16 channel, 24-bit system via the SPI bus.

No public road map

I’m particulary interested in countinuing to execute/ executing the Imp code in the event of an Internet failure…

This is coming in the next release which from the forum looks like a week or two. These are some of the features Hugo outlined…"It’s a big one! (has the fixed rate DAC, wifi off mode, shutdown handling, new wifi code and many many bug fixes)

Wake up is only on pin 1 - this is a hardware limitation. Wake reasons are:
WAKEREASON_POWER_ON Powered on
WAKEREASON_SW_RESET Restarted due to a software reset
WAKEREASON_TIMER Woken up after sleep time expired
WAKEREASON_PIN1 Woken up due to wakeup pin being active
WAKEREASON_NEW_SQUIRREL Restarted due to new squirrel code being loaded

@sjm: yes, the limitations of the SD card form factor don’t make it great for analog. The module has better ground (grounds have to be tied together, but the card has the contact impedance which causes problems), and has a discrete Vref pin too. The reason the ADC is shifted to be 16-bit range is for future expansion - should an imp with a 16 bit ADC come along in the future, code wouldn’t need to be changed to take advantage of it.

@tldstyl3: I’d like to see the circuit, really - ideally something we can replicate here. Note that some people have seen issues with sparkfun shields and pin 1 (physical disconnection), maybe you should try avoiding that pin when trying to prove out the issue you’re seeing?

First off, thanks for all of your replies! I love how many interesting and educated people there are out here!

@sjm - Yes, analog seems to not jive well with the SD… It’s really sad, too, because this is a useful and sometimes necessary functionality, which the Imp seems perfect for!

The sampler is one way to go, but it doesn’t allow me to sample more than 1 pin, which is a serious limitation.

I’m guessing I could get away with some ADC readings if I set an imp.sleep of at least half a second before taking the actual reading… However, I won’t make the mistake of leaving mission-critical readings to the ADC. Perhaps I’ll go digital for the temp reading, which I really don’t want spiking for no apparent reason.

The slightest spike on a digital rail will affect your analog readings.

Is there something one could do to minimize such spikes and thus improve ADC readings’ precision?

@controlCloud - Thanks for the reply! :slight_smile: I found several mentions of the cloud-less mode in posts saying that it should be deployed by the end of 2012 at the latest… Hope that we see this soon as it will add a whole new level of functionality to our beloved Imps.

@mlseim and @Hugo - I’m not doing anything that fancy, really. Attaching the schematic of my current setup:

  • A Photoresistor is connected to Pin 1, which I use to plot the current ambient light.
  • An LM35CZ precision temperature sensor is connected to Pin 2. It outputs a voltage relative to the current ambient temperature.
  • An LED is connected to Pin 9. It’s just used for signalling purposes.
Note that some people have seen issues with sparkfun shields and pin 1 (physical disconnection), maybe you should try avoiding that pin when trying to prove out the issue you're seeing?

I wasn’t aware of the Pin 1 issue in the Sparkfun shield… That would explain why I’m getting only strange values from my Photoresistor as of late… I’ll try and move that to another Pin and see if the issue disappears, but I would think that a $25 breakout would not have such a serious defect… Shame on you, Sparkfun!

Thanks for all of your help!

So: you should not be using 5v around the imp. You will be causing issues. It should not be powering R1/D1, and should not be powering the LDR divider.

If any input of the imp goes above 3.3v, it will certainly affect all the other inputs and/or possibly damage the imp.

I’d suggest you run the LDR and LED from 3.3v, and then put a divider on the OUTPUT of the LM35 to ensure the output never goes above 3.3v (unless you are sure the temperature ranges it’ll see will keep the output within the 3.3v range).

The sampler will get multi-channel support in time (it’s on the list), but the ADCs on the imp are just fine for this type of use. If you need absolutely reliable 12 bit sampling (+/- 1LSB, etc) - you need an imp module.

@Hugo - Thanks for the reply!

I’m aware that none of the inputs should ever go above 3V3, but is there another reason why shouldn’t I power directly from VCC if I’m sure that the Input will never go beyond 3V3?

I can even anchor it via a Zener or some other form of voltage regulator in cases where I’m not absolutely 100% certain I’ll be able to guarantee sub-3V3.

I’m wary of using the on-board 3V3 regulator since I need to take into account the total power, which I can drive from it. That’s not a problem when using VCC directly.

As far as the LM35 goes - I need to power it directly from VCC since it needs 5V to operate properly. I’m 100% sure that its output will never reach 3V3.

I’m still learning and I’m really glad that there’s someone out there willing to lend a hand and help us out when we hit a roadblock! Big thanks!

I have only played with the imp a little but saw some crazy graph data happening when I used two channels. Interestingly enough I was using a LM34 on pin1 and using hardware.voltage() for my second data channel. Using only channel 1 on Xively, I get nice smooth data.

When add the second channel, at some point the data values get swapped between the channels (a temperature of 3.29 and a voltage of 61). (I was measuring the temperature of the AC vent) Eventually the data goes get back to the correct channel but leaves glitch like noise in the graph.

When I return to a single temperature channel it goes back to smooth data. I expect I am not referencing the data correctly when I send to Xively so the value pairs get out of sequence. Rebooting the imp fixed it for a short while but the glitches came back. I could be doing multiple things wrong though.

This sounds quite different from what I’m experiencing and sadly I can’t think of anything which might cause this issue, especially if your code typically works, but goes wonky from time to time…

Perhaps someone more experienced can help you out.

@sdtrent very interesting. Have you got any standalone code that replicates that behavior, eg with server.logs instead of xively posts?

It’s certainly possible there’s a bug there, as the ADC is shared between all channels, but since a voltage reading is a float and normal ADC readings are integers, that actually sounds more like the data got confused somewhere in the HTTP POST to the graphing service.

@tldstyl3 using a 3.3v zener would be an acceptable workaround, yes (which could clamp a little low, but you can work out if that’s a problem for your application). Make sure that if you do clamp, whatever is driving the line will be ok though - you may need to add a series R.

Thanks for the feedback! I’ll try that and report back!

I’m currently experimenting with the Sampler taking an oversampled temperature reading and averaging all of the data in order to minimize noise.

My problem is that Squirrel always seems to wait until all other code is finished before firing the dataReady() event, which is not ideal for me since there’s a whole lot of stuff going on besides the Sampler itself.

I’d prefer to pause execution while the buffer fills up, execute the dataReady() function, which will average all of the readings in the buffer and then carry on executing having the now averaged reading.

Another point which I’d like to raise is that I start/stop the sampler when I’m not using the data so as to not consume unnecessary power.

There’s a lot of other stuff in my code, which are out of the scope of this issue so I’ll just give an overview of my code structure:

init() - this function initializes everything including the sampler itself. I also do sampler.start() here.

The sampler.stop() is called in the dataReady() callback.

This basically means that every time I call the sampler I just do one sweep of the buffer and then stop it. This should be sufficient for my needs.

takeAndSubmit() - this subsequent function takes all of the measurements from the respective sensors / devices and polls them out to services such as cosm/xively. There’s also another sampler.start() here so that I can fire up the sampler before I access the variable, which should hold the averaged value. Problem is that the variable for the temperature reading is initialized as 0 and comes up as 0, which means that it’s accessed before the first sweep of the Sampler.

This also means that each measurement is one step behind the actual iteration, i.e. the variable for the averaged temp is accessed before the Sampler can update the value.

I don’t know if anyone will be able to make anything out of the above, but I really hope that someone can step in and lend a hand.

Thanks in advance!