Reading Digital caliper with Arduino
#71
I thought I would go thru the interrupt routine to give you an idea of what I was trying to do.

The thought is that the interrupt routine will capture the stream of bits in a burst into an unsigned long. The interrupt will not try to figure out what the bits mean. That is the job of the application loop ... to take a completed burst and figure out what the bit pattern means based on the scale protocol.

Note that we don't care ... other than the value in the define ... if the transitions a rising or falling. All we are concerned about is that when a transition happens we are led to believe that the information on the data line is 'valid'. 

The first thing we do on a transition is determine the time of the interrupt and how long it has been since the last interrupt. They are both unsigned so we do not need to worry about things like rollover. We do this for all interrupts as only the very first interrupt we see does not care about the interval so lets make life simple.

Code:
void clockTransitioned() {
unsigned long timeAtInterupt = micros();
unsigned long intervalSinceLastInterrupt = timeAtInterupt - lastGoodClockTime;


The next thing we need to do is determine if this is the very first interrupt we have seen since we started the application. If it is the first one we have no idea where were are at with the clock so even our 'last time' does not have meaning and therefore our interval does not have meaning. Lets capture the time and set a couple of "here is where we are" sticks in the ground so we are be ready for the next interrupt.

Code:
// If we do not have our ducks in a row so we will get organized
if (!initialized) {
  lastGoodClockTime = timeAtInterupt;
  processingBurst = false;
  initialized = true;
}

All of the following interrupts fall thru to the next if. Now that we have a valid 'last time' and therefore a valid 'interval' we can see how long it has been since the last interrupt. If the interval is 'too soon' [we need to look at what we get from the scope to determine some of these values] then we consider it noise and just ignore it.

Code:
// Is the interrupt because of noise?
else if (intervalSinceLastInterrupt < CLOCK_NOISE_FILTER) {
  /*
   Note that we are going to do absolutely nothing in this case, not even update the last valid clock time.
   We are really waiting for a transition that is at least CLOCK_NOISE_FILTER later than the
   last transition that we thought was good.
   */
}

If it is not noise then maybe it is the beginning of a burst. We identify the beginning of a burst as having been [information from the scope goes here, but a relatively long time] microseconds since the last interrupt. If we think it is the beginning of the burst then do some things to start capturing the bit stream and that's it.

There is the possibility that we find what we think is the beginning of a burst while we are processing a burst. We will punt but this is the first draft so I have not written exactly what that means yet ...

And we probably need to do something more robust with capturing the data line to prevent noise from being an issue. Again, an exercise for later ...

Code:
// Is the interrupt because of a 'beginning of burst' pulse?
else if (intervalSinceLastInterrupt > MINIMUM_BURST_START_PULSE_WIDTH) {
  if (!processingBurst) {
    lastGoodClockTime = timeAtInterupt;
    burstStartTime = timeAtInterupt;
    inProcessBurstData = digitalRead(DATA_PIN);
    dataBitsReceived = 1;
    processingBurst = true;
  }


   // OK, we were in the process of receiving a burst but just got another 'beginning of burst' pulse.
   // We'll need to do something here but I will have to figure out exactly what after another cup of coffee.
   else {
   }


The only way we get this far is if we are initialized, do not think it was noise and do not think it looked like [i.e. looked like, but could have been invalid] a 'beginning of burst' pulse.

First thing to do is to see if we are in the process of accepting a burst. If not, then things are not going well. I am assuming another punt.

Code:
else {
 // If we are not in the process of reading a burst then we have a problem and need more coffee
  if (!processingBurst) {

  }

The stream should be completed in  [information from the scope goes here, but a relatively short time] microseconds so if it took longer than that we will again call the punter in.

Code:
  // If it has taken longer than we thought is should to show up then we have a problem ... see the coffe issue mentined earlier
  else if ((timeAtInterupt - burstStartTime) > MAXIMUM_TIME_FOR_A_SINGLE_BURST) {

  }

Finally it seems like we actually have another bit of data to capture. Shift the captured stream to the left one bit, capture the data line [see previous comment about noisy data] and increment the bit count.

Code:
  // We seem to be at the right place at the right time so grab what ever is on the data line.
  else {
    lastGoodClockTime = timeAtInterupt;
    inProcessBurstData << 1;                      // Make room for the next data bit
    inProcessBurstData | digitalRead(DATA_PIN);   // and then capture it
    dataBitsReceived += 1;

It is possible that we've now received all of the bits  [information from the scope goes here to determine how many bits we need] in the stream. If so then move the interim stream to somewhere an outside processes can easily get to it, increment a byte counter so the outside process knows a new stream is available and set things up so we are ready to go if we ever see another 'start of burst' condition.


Code:
    if (dataBitsReceived == DATA_BITS_IN_A_VALID_BURST) { // Are we done with this burst?
      capturedBurstData = inProcessBurstData;
      capturedBurstCounter ++;
      processingBurst = false;
    }
  }
}
}
  
Reply
Thanks given by:
#72
Right now I'm trying to get the internal pull-ups to work. The clock and data are working fine, they just aren't making it to the input pins because the pull-ups don't seem to be activated. I disconnected the interface board from the Arduino board and used a 1K pull-up resistor on the clock signal and it worked as expected so I know my interface circuitry is working. Something in the code is not activating the pull-ups in the Atmel chip. By the way, the pin numbers in your code should be pin 15 for the clock and pin 16 for the data.

Ed
Reply
Thanks given by:
#73
Got the clock and data lines working now. The "PIN" numbers in the code are not referring to the Atmel chip pin numbers but the digital pin numbers labeled on the board. Very confusing, I'm not sure why they did it that way. Anyway, the "PIN" numbers in the code should be 9 for the clock and 10 for the data.

I'm done for the night. A glass of wine is calling my name. Drinks

Ed
Reply
Thanks given by:
#74
I very much appreciate what you guys are doing. I will study these post hard and try to learn and understand what is developing.

Chuck
Micromark 7x14 Lathe, X2 Mill , old Green 4x6 bandsaw
The difficult takes me a while, the impossible takes a little longer.
Reply
Thanks given by:
#75
Here's the pin mapping that I found last night that led me to the solution to the pull-ups not working.

Ed

   
Reply
Thanks given by:
#76
My scope has problems but I was able to get some timing of the bits so here it is. These are as viewed on the Atmel input pins.

Clock high time = 200uS
Clock low time = 80uS
Time between nibbles = 370uS
Time to send 6 nibbles = 8.1mS
Time between groups of 6 nibbles = 105mS

This scope is going to be useless to decode the protocol but we should be able to do that using the serial monitor once we get the timing in the code set up right.

Ed
Reply
Thanks given by:
#77
Sparber got 8.9ms so it looks like you're right there. Can't you set your scope up to grab the entire burst and while it's stored use the horiz to spread it out and use the position to examine each nibble? I know I can do that on mine and yours is alot newer than mine and they're both the same series scopes.
Reply
Thanks given by:
#78
(03-21-2015, 02:07 PM)Vinny Wrote: Sparber got 8.9ms so it looks like you're right there.  Can't you set your scope up to grab the entire burst and while it's stored use the horiz to spread it out and use the position to examine each nibble?  I know I can do that on mine and yours is alot newer than mine and they're both the same series scopes.

No, like I've said, my scope has problems. If it was working as it should then it would be no problem at all.

Ed
Reply
Thanks given by:
#79
OK Arvid, I see why you used the pins you used. Bash

I've switched the clock to PIN 2 and the data to PIN 3.

I've got some questions though.

#define CLOCK_NOISE_FILTER 20 // How many microseconds long must the clock be stable for it to be consider 'good'
#define MINIMUM_BURST_START_PULSE_WIDTH 20 // At a minimum, how many microseconds long is the pulse at the beginning of a burst
#define MAXIMUM_TIME_FOR_A_SINGLE_BURST 10000 // The maximum amount of time that a burst should take before considered invalid


The first line I'm assuming you're referring to after the edge detection we need to see the low level for 20 uS to be considered a good pulse. Assuming a falling edge interrupt trigger. Correct?

The second line is similar to the first but used when starting a new burst. Correct?

What are you defining as a burst? All 24 bits or a nibble? What is the time base for this, microseconds?

Ed
Reply
Thanks given by:
#80
The value for the noise filter looks good.

All 'times' are uS.

I defined a burst as 'all the bits' for a single reading. I was hoping for a very general 'capture all the bits' routine. The concept of nibbles and what the bit stream means is left for the external routine. The assumption is that 'if we don't get the entire burst in xxx time then something is wrong and knowing which of the nibbles did not meet the inter-nibble timing requirement doesn't really matter'. Of course this assumption is open to challenge and discussion ... as is all of the code. 

The minimum_burst_start_pulse_width is how long we expect the clock to be high after the end of a burst or before the next burst starts. It looks like you are seeing 105mS so 90000us might be a good place to start.

maximum_time_for_a_burst seems to be about 8.1mS so a value of 9000uS seems like a reasonable starting point.

data_bits_in_valid_burst would be 24.

Arvid
Reply
Thanks given by: EdK




Users browsing this thread: 11 Guest(s)