readadc accuracy

BeanieBots

Moderator
Any help appreciated Jez. Go for it.

A little more for Boriz's question.
Your example measures distance, your control effects speed.
What does your output control? (maybe torque).
So, without being funny about it, how would control speed? PID maybe!
What is your feedback for speed? (maybe differential of position!).
Controlling power into a motor does NOT control speed. It controls torque.

Basic equations of motion:-
F=ma. (torque effects acceleration proportionally)
S=ut + 1/2 at^2 (distance is integral of velocity)
v=u+at (velocity is integral of acceleration)

There's simply no escaping calculus if you want to control things!
If you only have one type of sensor, that is, distance, velocity or acceleration, you will have to perform calculus to determine the others.
Alternatively, you could use proportional only but would need a sensor for each. Namely, a distance sensor (POT), a velocity sensor (tacho) and an acceleration sensor (accelerometer).

Alband has a postion pot. So to "go faster", first he must know the derivative of position. It's not complicated, it's "how far have I gone in the last X seconds?". ie the rate at which distance changes. Namely the derivative of position. And so on for all the other terms.
 

boriz

Senior Member
"There's simply no escaping calculus if you want to control things!"

I've been controlling things for years and never studied calculus. I'm sure there's a nice integer solution just waiting someplace. I might even find it (when I need it). In the mean time, my algorithmic approach to such problems as an alternative to hard math, has worked ok for me so far. I guess it’s because I learned 6502 machine code instead of math :)

Op-amps were originally designed as analog computational elements during the start of the computer revolution (calculating artillery trajectories). Maybe an op-amp would be ideal for this sort of app. It could be argued that a well designed op-amp approach is actually better, because it’s faster and more accurate (no rounding errors). But the D-to-A at the start and the A-to-D at the end would spoil that I suppose.
 

alband

Senior Member
Need I2C help

Code:
		#PICAXE28X2
pause 1000
high B.5
high B.4
pause 1000
		
		hi2csetup i2cmaster,%00110011,i2cslow,i2cbyte
		


main:		'hi2cout 0,(0x80)
		'hi2cin %00000011,(b2)
		'hi2cin %00000010,(b3)
		'hi2cout %00110010,(%00110011)
		'hi2cin (b2)
		hi2cin 3,(b2)
		hi2cin 2,(b3)
		'hi2cin %10000010,(b1)
		'hi2cin %10000100,(b2)
		let bit0 = bit20
		let bit1 = bit21
		let bit2 = bit22
		let bit3 = bit23
		let bit4 = bit24
		let bit5 = bit25
		let bit6 = bit26
		let bit7 = bit27
		let bit8 = bit28
		let bit9 = bit29
		let bit10 = bit30
		let bit11 = bit31
		sertxd (#w0,",")
		'sertxd (#b1,",")
		'sertxd (#b2,",")
		'debug
		goto main
This is the latest version of my code, and unfortunately I have got to a point where I am fairly sure it is right, yet it is still clearly is wrong.
The large "let bit" sequence is to re-arrange the bits so that they should leave w0 in the right order. I don't know whether this is correct, but I can sort that out. Crucially, it is still returning 255 from the I2Cin (4095 when they are reorganised), and I have found out that "hi2cin" returns 255 when "the i2c hardware is incorrectly configured, or the wrong i2cslave data has been
used".
I've checked the connections and they are fine. I have the pull-ups on each line. CS is high for I2C coms, ADDR is high, to make the address %00110011. I really don't know what else to do or what else I could change. As you can see from the code, I have a lot of options I have been trying but none have worked. :(

Here's the datasheet again.
Thanks for any help.
 

Dippy

Moderator
I haven't looked at the rest of your code.
I'm guessing a bit here (based on other Data Sheets)
Try 00011001 for your SAD.
 

alband

Senior Member
Same result.

The second last bit is definitely "1" because it is determined by a pin, which I have set high.

Thanks though.
 

alband

Senior Member
Does anyone have any surgestions? :(

For instance, I'm still not sure whether I should have:
Code:
hi2csetup i2cmaster,%00011011,i2cslow,i2cbyte
or:
Code:
hi2csetup i2cmaster,%0001101,i2cslow,i2cbyte
(without the last digit of the slave address)
Also is my setup for reading from it right?

Should I use hi2cout to tell the accel the address I want to read then use hi2cin to read it
or
should I do it all in one command "hi2cin %00000011,(b2)". If so should it be "hi2cin 3,(b2)" instead?

There is of course the problem that I think I've tried all the possible combinations of these and it hasn't worked at all. However, I don't know if any are right and cant eliminate any myself.

Some help would be really appreciated here. :eek:
 

hippy

Ex-Staff (retired)
The datasheet shows the 7-bit I2C Device Address is 001100X, where X=1 in your case, and the redundant bit added as lsb to make it 8-bits, gives %00110010. Though I don't think having lsb set makes a difference.

You can also try with normal I2C rather than HI2C, "I2cSlave %00110010, I2CSLOW, I2CBYTE" and use "I2cRead 3,(b0)" etc, and with address %00110000.

The device seems to do clock-stretching and I don't off-hand know how the PICAXE will deal with that in either mode.

It's always hard to get a 'back box' component working when it doesn't and won't do anything much until it does work. Worse case scenario is you have to write bit-banged code to get it to work or to find why it isn't working. If the hardware isn't correct, wrong voltage, enabling chip too soon, swapped SDA or SCL, other wiring mistake or configuration error, or a dead chip, you will be on a hiding to nowhere. Bit-banged code will allow you to single step the signalling at a speed you can see what interactions are happening. If you put a scope on the lines you should be able to see the comms packet and take note of ACK and NAK on the I2C bus. Maybe make sure you can access an I2C Eeprom on the bus just to make sure that is working.

Is the chip returning analogue readings ?
 

Dippy

Moderator
Phew boriz, that's a lot of bedtime reading that won't get read :)

On the face of it, it looks like pretty standard I2C to me.
As hippy suggests; 'scope it to see if there are any transactions.

I'm afraid that when using unusual (or novel/new) chips these are the problems and without it in front of me I can't suggest anything other than keep plugging away.

However, if , after a while, you have the urge to phone Smaritans then stop - and try SPI.
Believe me, we've all had these issues. It took me a day to write some soft SPI routines for single wire SPI so I know what it feels like.

If all fails then it's back to reading ADC I guess... full circle.
 

alband

Senior Member
Hmmm,
I've justed "scoped" the two lines. This is of course quite hard as I'm still using a piece of computer software so it has lots of that AC mess up stuff andof course I can't "record" the line like a graph. Thus, making reading 100khz pulses quite hard. One thing I have noticed though, is that both channels are exactly the same, even if I increase the amplitude and time period so that I can see the individual pulses. The two lines are exactly the same. I've checked all the resistances between the two lines at verious points, connected and unconnected and I is never shorted.

Any thought?
I'll try and get some pictures online tonight. But they won't be great quality - I need to get a real scope or something.
 

alband

Senior Member
Here, they are exactly the same.
I'll get some other pictures that show the "context" of these pulses. Each of these mini-double-pulses, makes up a group of pulses, that make up bigger groups. E'll explain in the morning, but as you can see, they are exactly the same.
 

Attachments

hippy

Ex-Staff (retired)
I guess we'll have to wait for your explanation of which two lines you scoped and what we are actually looking at, but SCL and SDA should be appreciable different when looking at the period of I2C communication.
 

alband

Senior Member
Well, these are the sda and scl so it is very odd. I'll change the code after breakfast so that i can either prove they are those lines or find out what's wrong (hopefully the latter).
 

Dippy

Moderator
After breakfast?
Its nine-thirty!

Check your lines, something looks iffy.
SCL being a clock should look like a clock.

Try again but change your code so it sends just a byte or two in a loop, then try and store both SCL and SDA. Do a write only if you can so the SDA line doesn't get returned data to confuse the issue. Check for ACKs.

Then move onto a data request and scope that.

But first, rush out with a £1000 and buy a Tektronix ;)
 

alband

Senior Member
I ran some code that put the two I2C pins high an low to see if there was any separation, and I only got pulses from one pin. I think the problem was that I had it plugged into a microphone input on the PC which must be designed for mono signals and so only read one of them. I now have it using a "line-in" on the back of the PC and managed to get the two highs and lows.
This is in the second attachment, along with the code in the same picture. You may notice however that the line doesn't appear to stay on the trace, but this just must be because it is designed for music so has lots of that AC muck up stuff.

The fist attachment shows what happens with the previous code:
Code:
		#PICAXE28X2
pause 1000
high B.5
high B.4
pause 1000
		
		hi2csetup i2cmaster,%00011001,i2cslow,i2cbyte
		


main:		'hi2cout 0,(0x80)
		'hi2cin %00000011,(b2)
		'hi2cin %00000010,(b3)
		'hi2cout %00110010,(%00110011)
		'hi2cin (b2)
		hi2cin 3,(b2)
		hi2cin 2,(b3)
		'hi2cin %10000010,(b1)
		'hi2cin %10000100,(b2)
		let bit0 = bit20
		let bit1 = bit21
		let bit2 = bit22
		let bit3 = bit23
		let bit4 = bit24
		let bit5 = bit25
		let bit6 = bit26
		let bit7 = bit27
		let bit8 = bit28
		let bit9 = bit29
		let bit10 = bit30
		let bit11 = bit31
		sertxd (#w0,",")
		'sertxd (#b1,",")
		'sertxd (#b2,",")
		'debug
		goto main
Each of those low pulses are actually a pair of pulses, shown in my previous post. I will post those again as they are slightly different.
As you can see though, the lines are still the same. The are now slightly different because they aren't the same line, but they follow almost exactly the same pattern.

I'll keep trying some other stuff, but I really don't know what's going on :confused:
 

Attachments

alband

Senior Member
This is a "close up" of each of the spikes in the last post.

Addit: I just did a test where I put the high-low stuff at the front of the I2C stuff. That happened as expected - same traces just one after the other. While it was doing the I2C loop, I just tried taking the pull-up 4K7 out of the clock. When I did so, BOTH lines went dead. I did the same with the data pull-up and BOTH lines went dead.
I don't if that means anything to anyone.
 

Attachments

Last edited:

hippy

Ex-Staff (retired)
This is going to be tough going if the AC coupling of the scope gets in the way, however at higher speed it has less of an affect so should be usable at least to see that roughly what should be happening is happening.

First, cut your test program down to the very minimum with enough time between events to be able to show one transaction on the I2C bus ...

I2cSlave ...
Do
I2cRead 3, (b0)
Pause 500
Loop

Now set the scope to trigger so that you get just one transaction shown on the scope, zoom in as far as possible so it's still on the screen, and make sure SDA is a trace at the top and SCL a separate, distinct trace at the bottom.

I don't know / understand what these double pulses are, but nothing looks like legitimate I2C to me. It could be that the scope just isn't up to the task.

Also, did you try using normal I2CSLAVE, I2CREAD ?

Have you tried connecting I2C Eeprom to SDA and SCL to prove that works okay ?

It would be best to get an I2C Eeprom working then run the test program above, then you can check the scope is showing what it should be showing. If you cannot see the I2C transaction clearly on a known working system this approach is not going to work.
 

alband

Senior Member
I've worked some stuff out.
The pattern was space, the two mini lows, then repeat. Each space turns out to be the bits in the code where it goes through all the "let"s. The two mini lows are actually each of the "hi2cin"s.

So I've now changed my code, so it only has the setup and then one hi2cin command in a loop. I then zoomed into this to try and figure out what was going on and see if I could see all the "stuff" going on within each "hi2cin" command, but it was useless. I later found out why. This scope can only (huh, only) sample at 44100samples/sec with 16bit/sample so even with it running at 100khz (I2Cslow) there would be no chance of seeing the clock pulses.

Basically, I actually do need to run out with that £1000 :eek:. This is a slight issue.
I'll see if I can find some faster software, but the 44100 might be the limmit of the hardware.

Edit: @Hippy: We posted at the same time but irony is present and I have actually done just that :). I haven't tried using the normal commands and will do that now (without scope). I have tried an EEPROM chip with no success. It is a ST microelectronics version of the 24LCxx series from microchip so it is very similar to the one in the I2C example, but I de-soldered it from a TV so it could be fried.
 

Attachments

Last edited:

Dippy

Moderator
Oh dear.... this is where you have to move from toys to proper stuff.

I can't suggest anything with proper info. As the Startrek computer would say: "Insufficient Data" beep beep beep.

hippy will get you sorted.


"It is a ST microelectronics version of the 24LCxx series from microchip so it is very similar to the one in the I2C example, but I de-soldered it from a TV so it could be fried."
- always the risk with hackaphilia.
 

hippy

Ex-Staff (retired)
Getting any I2C working is really a prerequisite. There are a couple of things you can do to help see the signals at a speed which your scope can cope with ...

1) Change I2CSLOW to 255

2) Use "SETFREQ K31" or some other under-clocked setting ( k250, k500, m1, m2, m4 ).

The only thing you need to avoid is running so slowly that the AC coupling obscures or distorts what you are wanting to see. With just a working single I2CREAD you should see 18 (?) low-going pulses of SCL in each I2C burst.
 

SilentScreamer

Senior Member
I'll see if I can find some faster software, but the 44100 might be the limmit of the hardware.
No idea if this will work but its worth a shot.

Go into control panel, make sure it is in classic view, look for something named "sound". On the recording tab, double click on whichever device you are using. On the advanced tab there will be a drop down list for the sample rate, change it to the highest setting.

I am currently on vista so the above may not be perfect. If you can't find it using those instructions I'll load up XP and give you the correct ones.
 

alband

Senior Member
Perfect. I didn't know it is possible to use "255" instead of I2C slow, but I should have thought of changing the frequency.

Code:
		#PICAXE28X2
pause 1000
high B.5
high B.4
pause 1000
setfreq m1

		i2cslave %1010000,255,i2cword

main:		writei2c 1,(13)
		pause 50
		readi2c 1,(b0)
		sertxd (#b0,",")
		goto main
The Read line is SDA and green must be clock (based on the traces).

However, it still returns 255 indicating no response. I assume where there are "gaps" in the red, is where the EEPROM was meant to respond.

Addit: @SS: I think I've found the XP equivalent but it is already at "best" setting. It wont give a choice of numbers though, only a slider between "good" and "Best".
 

Attachments

Last edited:

hippy

Ex-Staff (retired)
Bingo ! That does look like an I2C header ...

Start (S), SDA goes low followed by SCL going low
7 x I2C address bits ( msb first ), SCL pulses high
Write/Read bit (W=0/R=1), SCL pulses high
Ack/Nak bit (A=0/N=1), SCL pulses high, I2C device replies
Stop (P), SCL goes high followed by SDA going high

So, that's "S0101000WNP", and that's a NAK because the 7-bit I2C address is 0101000 when it should be 1010000 for Eeprom.

Change to "I2cSlave %10100000,255,i2cword" and you should get "S1010000WA...", though most likely to see ""S1010000RA..." which is the first transaction.
 
Last edited:

alband

Senior Member
Bingo ! That does look like an I2C header ...

Start bit (S), SDA goes low followed by SCL going low
7 x I2C address bits, SCL pulses high
Write/Read bit (W=0/R=1), SCL pulses high
Ack/Nak bit (A=0/N=1), SCL pulses high
Stop bit (P), SDA goes high followed by SCL going high

So, that's "S0101000WNP", and that's a NAK because the 7-bit I2C address is 0101000 when it should be 1010000 for Eeprom.

Change to "I2cSlave %10100000,255,i2cword" and you should get "S1010000WA..."
...that is cool.

Err, I added that zero and things have changed considerably. Is this what you expected?
(I also swapped the colours so it's easier to read)

Edit: whoa, that's just the first of two, I didn't see the second one, it's coming...

Addit: those are the final images. One thing of note, is that it returns "1" now, not "255" since I added the extra zero. However, the "1" doesn't change at all, even If I change the written variable:
Code:
		#PICAXE28X2
pause 1000
high B.5
high B.4
pause 1000
setfreq m1

		i2cslave %10100000,255,i2cword
		let b1 = 0

main:		inc b1
		writei2c 1,(b1)
		pause 50
		readi2c 1,(b0)
		sertxd (#b0,",",#b1,",")
		goto main
 

Attachments

Last edited:

hippy

Ex-Staff (retired)
Without studying the traces they look like I'd expect. An I2C Read is "S 1010000R A aaaaaaaa A aaaaaaaa A dddddddd N P" ( a = address, d = data returned ), and an I2C Write is an aborted I2C Read with a repeated Start "S 1010000R A aaaaaaaa A aaaaaaaa A S 1010000W A dddddddd A P" ( a = address, d = data to write ) so it gets complicated.

As to why it's only ever returning "1" ...

Should the Eeprom be I2CBYTE addressed rather than I2CWORD ?
Do you have WP pin connected to 0V ?
Is the program resetting ? - Add a SERTXD("RESET") before 'main:'
 
Last edited:

alband

Senior Member
:D
Guess what...

It works! I (well) have made I2C WORK! heh. I am now chuffed to bits.

It was the word/byte thing. Now I get, "1,1,2,2,3,3...".

SO I'll try out code like this with the accel, but first. I didn't quite follow post 66.

Why did you add an extra "0" after the address?
 

alband

Senior Member
Right, I've sorted some stuff out.

I've managed to get the accel to acknowledge once, but then my understanding of the trace gets lost.

So far as I can tell, it goes: S0011001WA then I get lost, but the sequence in the datasheet says that after the accel acknowledgegs, the PICAXE should send the 8bit register address (RA) but I cant see that. I can however, see the clock line stopping for about 2 bits and then the final stop bit being sent.

There also appears never to be the second transaction where it should go S0011001RA.

The full thing should be:
Code:
Master:                        S0011001W 00000011 S0011001R         NAP
Slave:                                  A        A         AXXXXXXXX
Is that correct?

Currently it seems to get to:

Code:
Master:                        S0011001W ??P
Slave:                                  A
 

Attachments

hippy

Ex-Staff (retired)
Do just the Read and see if you can get meaningful stuff there. Then move on to just Write then using both. I2cRead 3,(b0) should give ...

"S 0011001R A 00000011 A dddddddd N P"

According to my I2C spec sheet, W=0, R=1, but you seem to be getting the opposite of that.
 

alband

Senior Member
That is currently what I'm trying to do.

Errrm. I think I got my last post wrong. It isn't acknowledging (and isn't in the last post's attachment).
Looks like I still have a way to go before it will work.

I did however go back to the EEPROM to try and figure this out and managed to get some good examples of read and writing to it.

Edit: forgot to mention, the attachment needs to be changed to .ppt
 

Attachments

Last edited:

alband

Senior Member
This is the current code, but it still isn't working.
Code:
		#PICAXE28X2
pause 1000
high B.5
high B.4
pause 1000
setfreq m1

		i2cslave %00110010,255,i2cbyte
	
		let b1 = 0
		SERTXD("RESET")
main:		pause 50
		readi2c 3,(b0)
		sertxd (#b0,",")
		goto main
The SAD gives the right combination of "0"'s and "1"'s but the accel still isn't acknowledging.
 

Attachments

hippy

Ex-Staff (retired)
Interestingly, at the end of the SCL pulse for ACK/NAK there's a glitch from high towards low, so it looks like something is happening though I'm not sure what or why.
 

alband

Senior Member
I found something: the accel's clock line was plugged into the data line so I thought that would be the problem, but I've sorted it out and the trace looks exactly the same.

To me it looks like the accel is trying to acknowledge but can't, I'm using 4k7 pull-ups just now so I'll try using some higher values inc. non at all.
 

BeanieBots

Moderator
No, you MUST have pull-ups.
4k7 should be OK, REDUCE the value, (maybe as low as 1k8) for long wires or noisy situations. No resistors and it won't work.
 

Dippy

Moderator
If you've spotted a basic error like that then you'd better double check everything else.

I take it you have:-

Accel SDO (output) to PIC SDI
and
Accel SDI (input) to PIC SDO
??

Are you 'enabled' properly?

What supply voltages are you using for Accel and PICAXE?
 

alband

Senior Member
No, effect changing the pull-up values except that the logic high state lowers.

I've tried slow it right down to k250 (was on m1) to see if I could spy what is going on, and it appears that the SDA is pulled right down where the accel should acknowledge, then then or course swings straight back up. I'm sure it's the PICAXE that pulls the line high where the should be an acknowledge, or at least that it isn't the accel; if I unplug the accel's SDA, it gives the same reading, but the line also gives the minute low, just before, so the PICAXE must be doing that too.

In the datasheet there is a table for electrical perimeters, inducing clock speed. There are "min", "typical" and "max" columns but for the clock speed it just gives 400KHz in the typical column and no further information. Is it reasonable to assume it can to 400KHz and anything less than?
 

hippy

Ex-Staff (retired)
If SDA is being pulled low then that suggests the ACK is present. The PICAXE isn't pulling the line high, the pull-ups do that; at the time the ACK is being checked for, the PICAXE sets SDA as input, the line 'floats' ( but pulled-up by the R ) and pulled to 0V by the I2C device's open collector to 0V if it ACK's. A NAK is a no response where the bus is left high.

A glitch is possible when the PICAXE finishes the SCL strobe for ACK/NAK but one would need a good quality scope trace of what's happening and its timing relationship with SCL edges to tell more about that.

One thing you can try is reading some other register than "3"; choose something which isn't part of an X, Y or Z value, eg, a status or configuration register.

Yes, with 400kHz max, anything up to that will do. It should be possible to run I2C down to almost zero-Hz speeds.
 

BeanieBots

Moderator
I'm no expert on I2C but my understanding is that it will work at any speed from DC to the max. specified. Hence, you can bit-bang in code.
(I could be wrong and it could be device dependant)

As for the hardware, the PICAXE does not (should not) pull either of the lines high. That's the pull-up resistor's job. Both PICAXE and I2C device should operate like an open-collector. (just like an LM339 comparitor!).
That way, no damage can be done if one device wants the line high and the other wants it low. Don't forget, the data line is bi-directional so a 'clash' could cause damage if either device could DRIVE the line high.

EDIT: Speed issued confirmed by Hippy above.
 
Top