NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » Digital kettle project

July 27, 2010
by sonierm
sonierm's Avatar

Hello everyone, first post here! So I have completed the guide and some tutorials now I am interested in making my own project.

Background: I drink lots of green tea but the problem is the auto off on the kettle is too high and the water is way too hot.

Solution: make an interface that turns of the kettle when it reaches a set temperature.

The project The temperature will be set by a rotary encoder and displayed on a 7 segment display. There will be a second 7 segment to show the current temperature. Once the temp is set, the MCU will activate the relay and start the kettle. When the two temps are equal, the MCU will shut of the kettle.

So the questions I have are: 1)Do I need a driver for the 7 segments? Can you recommend one and maybe give a digi-key product number? 2)Can anyone recommend encoders? Anyone ever use them? How do I implement this code? 3)Any suggestions?

July 27, 2010
by bretm
bretm's Avatar

Do you want LCD or LED display? I'm partial to LED, but you can't really run those off a battery for very long. If you want LED, I'd consider something like this because it's easy to hook up to the MCU and easy to program. The only problem is that there isn't a gap between the two sets of two digits. You could use the colon for that. Otherwise you can use something like the MAX7219/MAX7221 and get the displays separately and position them however you want.

July 27, 2010
by sonierm
sonierm's Avatar

I defiantly want LED. I was thinking more like four of these

How do I use those drivers?

July 27, 2010
by bretm
bretm's Avatar

The datasheet for those drivers is here. The first page has a diagram showing the three pins you need to connect to the Atmega. Then you use SPI to send it pairs of bytes, giving it commands listed in Table 2 on page 7. You can set the digits individually, adjust the brightness, turn the display off/on, limit the digit count (which you probably want to do since you're using fewer than 8), and display a test pattern.

July 27, 2010
by sonierm
sonierm's Avatar

okay perfect so I will get that driver, any ideas about encoders?

July 27, 2010
by sonierm
sonierm's Avatar

okay perfect so I will get that driver, any ideas about encoders?

July 27, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi sonierm,

This sounds like a very neat project. There is a huge price difference between kettles with a temperature control and those that just boil water. I have a couple of suggestions.

Have you considered using the LCD screen included with the kit? I think it might give you a lot more freedom to display all sorts of things like the set temperature, current temperature, perhaps even estimated time left? Since I assume you are building this into an electric kettle I imagine there is a wall outlet near by from which you can power the NerdKit. So you could run the LCD with a backlight on and all and have yourself a really neat display.

There is potentiometer included with the NerdKit (little blue guy with 3 legs). You should be able to use this (along with a little bit of circuitry, and the ADC to set a value. Alternatively you could use the 7 position dip switch to represent a 7 bit binary number =).

Have you thought about how you are going to read the temperature. You definitely don't want to stick the temp sensor we provide straight into the hot water you intend to drink. The plastic casing is not meant to be immersed in water, and is not designed to be able to touch food. One solution is to stick the temp sensor on the outside, then calibrate the sensor to account for the heat loss through the wall of your kettle to the sensor. You could also have some sort of probe like we had in the Meat Thermometer tutorial.

Also be very careful when dealing with 120V appliances in your house. Especially those that heat up really hot and can cause fires. Make sure you triple check all your wiring before going live with it. I would highly recommend you build the system as a temperature monitor first, such that it displays the temperature and you manually shut off the kettle. I would also make sure your design keeps all the mechanisms of the original kettle intact, like the auto shutoff on boiling.

I can't wait to see this project develop!

Humberto

July 27, 2010
by bretm
bretm's Avatar

If you do want to use a rotary encoder, there are lots to choose from on Digikey. It just depends on how you want to connect it, mount it, whether you want detents, number of pulses per rotation, etc. I like the idea--I think it'll make a very user-friendly way to change the value.

I think you'd probably want a Quadrature (Incremental) type, not a BCD, Gray-code, or other (Absolute) type, because you don't care what the position is, just which way it's turning and how fast.

July 27, 2010
by sonierm
sonierm's Avatar

I would much rather use the small 7 segments over the LCD.

I think encoders would be a good learning experience and I like the "smoothness" of the turning, if that makes seance. But I do have a few linear 10K pots around if I chose that route.

I am basing the temperature reading from an old book I have. The book has a project to send data from a coffee pot to a web server.

Here are the pages with the sensor: 1 2 3

I got the food safe tube and silicone today. I am out of town tomorrow till Monday but when I return, I will begin making the temp prob.

July 29, 2010
by sonierm
sonierm's Avatar

I have been looking at the encoders but I still have a few questions

some have 3 pins like this and some have 5 pins like this

Both are Quadrature(Incremental), which is best?

July 30, 2010
by bretm
bretm's Avatar

The 5-pin one has a push-button switch connected to the other two pins. Which one is better depends on whether your project needs that switch or not.

It might be handy to prevent accidentally changing the setting, e.g. push the switch to go into "edit mode" and push it again to lock in the new setting.

August 11, 2010
by sonierm
sonierm's Avatar

I am completly stuck trying to get the encoder to work, I have no idea how to code it.

August 11, 2010
by sonierm
sonierm's Avatar

completely**

August 11, 2010
by Ralphxyz
Ralphxyz's Avatar

Where are you stuck? You could use the tempsensor project and just replace the LM34 with the encoder just to see it work.

We can not read minds so give us a hint where you are stuck and we will get you free.

Ralph

August 11, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi sonierm,

The first step is to figure out exactly how your encoder works. The datasheet should give you a lot of information about that. I'm not sure how familiar you are with the general idea of how the encoders you linked to work. What they basically are is little switch the opens and closes as you move the shaft around. You hook up the circuit so that it generates high and low voltage pulses, and you count the number of pulses to know how far the shaft has moved. You probably have two different outputs that are offset a bit so that you can tell which direction you are turning based on which pulse comes first. Ralphs suggestion to hook it up to the ADC is a great idea so that you get a feeling for what you are dealing with. Once you understand your encoder you will likely want to look into pin change interrupts to detect your high and low pulses. Check out the interrupts tutorial for a bit of info on those.

Humberto

August 12, 2010
by sonierm
sonierm's Avatar

Hello

I have already read the datasheet and it does not contain a lot of information. Here's the one I was looking at, its linked off of digi-keys site. Link

I have also watch this. It gave me a good idea of how it works.

I also just watched the interrupt video. It was great help but I still am not sure how to get started at this. How do I know what the pulses are? and how do i decode them to just increase/decrease an int?

Thanks for all your help guys:)

August 12, 2010
by sonierm
sonierm's Avatar

Hello

I have already read the datasheet and it does not contain a lot of information. Here's the one I was looking at, its linked off of digi-keys site. Link

I have also watch this. It gave me a good idea of how it works.

I also just watched the interrupt video. It was great help but I still am not sure how to get started at this. How do I know what the pulses are? and how do i decode them to just increase/decrease an int?

Thanks for all your help guys:)

August 12, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi sonierm,

If you understand how the encoder works, and how to hook it up such that you get pulses out of it as you turn the shaft, then you are at least half way there. The rest is a code problem, here is an outline of the things your program probably needs to do:

  1. Set up a pin change interrupt on the line the pin that is pulsing.
  2. Make one global variable to hold the current pulse count
  3. In the interrupt handler for the pin change interrupt (which will fire every time the line changes from high to low, or low to high), increment the counter by one.
  4. In your main loop use changing value of the counter to infer the shaft is moving, as a first pass I would just print the current counter value to the LCD.

This is the most basic program that will get information from your encoder. Once you get this working you will want to read both channels so you can tell which direction you are turning. You will also probably want to add some debouncing in software to prevent mechanical jitter from throwing your count off. Give writing the simple program a shot, and post it up if you have issues. I'm sure plenty of folks here would be glad to help.

Humberto

August 12, 2010
by bretm
bretm's Avatar

If you read the two inputs into two pins and then combine the two bits into a single two-bit number, you'll end up with a number from 0 to 3. Example:

Value    Input A    Input B
  0         0          0
  1         0          1
  2         1          0
  3         1          1

You can do this by doing something like "v = b | (a << 1);".

Now you can see that if the encoder is turned in one direction, you'll see the value transition from 0 to 1, or from 1 to 3, or from 3 to 2, or from 2 to 0.

In the other direction you'll see transitions from 0 to 2, or from 2 to 3, or from 3 to 1, or from 1 to 0.

If you see any other transitions, such as 0 to/from 3, or 1 to/from 2, you can't tell which direction happened so you'll have to ignore it.

In the case of the switches bouncing (which they will) it will look like the encoder is quickly changing direction back and forth. How you handle that case depends on what you want to do. If you're just incrementing or decrementing an integer depending on which direction you're going, then maybe you don't have to do anything because your integer will jump up and down but won't wander off into some bad territory.

August 12, 2010
by Ralphxyz
Ralphxyz's Avatar

Well the optical encoder should not bounce according to the video presentation.

I suppose that is why you pay a premium for the optical encoder.

Thanks for this thread it really has peaked my interest, please keep us posted with how you progress so we can use all of your hard work.

That spec sheet you referenced is rather bad.

Ralph

September 08, 2010
by sonierm
sonierm's Avatar

Howdy

Sorry its been a while, I have moved away from home for school. I am now settled in and I have had a chance to work on the code. I have tried many different approaches and I still can not get it perfect.

So if it works perfectly, the ISR should fire 4 times. Now the problem is it dose not always do that. In testing, I noticed it doesn't always work perfectly, sometimes it only fires 3 times and sometimes only 2. I would need a code solution to this problem.

So the code right now assumes its firing on first increment, then it checks to see that if 'A' is high and 'B' is low or vise versa then increments/decrements the count. It works okay i guess...

Heres the code

ISR(PCINT1_vect){
  if (firstrun == 1)
  {
    if((PINC & (1<<PC1)) && (!(PINC & (1<<PC2)))){
      count += 1;
    }
    if((PINC & (1<<PC2)) && (!(PINC & (1<<PC1)))){
      count -= 1;
    }
    //firstrun = 0;
    return;
  }

  firstrun = 1;

}

So I think one start of a solution would be to have separate ISR functions for the two Channels. I'm not really sure how to do this. If anyone can help that would be greatly appreciated.

I am also curious as to how to code some debouncing, I understand what happens I just don't know how to transfer a solution into code.

As always your help is appreciated. cheers Matt

September 08, 2010
by bretm
bretm's Avatar

Just because A is hi and B is lo, or vice versa, doesn't tell you which direction the shaft it turning. It will go through that state (and the other three states) in both directions. What you need to do is observe the sequence of the states. I might try something like this:

volatile uint8_t previousState;

ISR(PCINT1_vect)
{ 
    uint8_t oldState = previousState;
    uint8_t newState = (PINC >> PC1) & 0b11;   // get both PC2 and PC1
    previousState = newState;
    uint8_t changedBits = oldState ^ newState;

    if ((changedBits == 0b00) || (changedBits == 0b11))
        return;   // no change or two changes, can't tell which direction

    switch (oldState)
    {
        case 0:
            count += newState == 1 ? +1 : -1;
            break;

        case 1:
            count += newState == 3 ? +1 : -1;
            break;

        case 2:
            count += newState == 0 ? +1 : -1;
            break;

        case 3:
            count += newState == 2 ? +1 : -1;
            break;
    }
}
September 09, 2010
by bretm
bretm's Avatar

Another way to look at it is that the two encoded bits represent a Grey Code of the shaft's position from 0 to 3. If you undo the Grey coding you'll get the position, and if you subtract the two positions (mod 4) you'll get the direction.

volatile uint8_t previousPos;

ISR(PCINT1_vect) 
{      
    uint8_t oldPos = previousPos;     
    uint8_t newState = (PINC >> PC1) & 0b11;      // get both PC2 and PC1     
    uint8_t newPos = newState ^ (newState >> 1);  // undo Grey code   
    previousPos = newPos;

    switch ((newPos - oldPos) & 0b11)
    {
        case 1:
            count++;
            break;

        case 3: // (-1 mod 4)
            count--;
            break;
    }
}
September 09, 2010
by Ralphxyz
Ralphxyz's Avatar

bretm, how are you getting both PC1 and PC2 with:

uint8_t newState = (PINC >> PC1) & 0b11;      // get both PC2 and PC1

Ralph

September 09, 2010
by bretm
bretm's Avatar

PINC contains all 8 pins:

+-----------------------------------------------+
|                   PINC byte                   |
+-----+-----+-----+-----+-----+-----+-----+-----+
| PC7 | PC6 | PC5 | PC4 | PC3 | PC2 | PC1 | PC0 |
+-----+-----+-----+-----+-----+-----+-----+-----+

+-----------------------------------------------+
|                  PINC >> PC1                  |
+-----+-----+-----+-----+-----+-----+-----+-----+
|  0  | PC7 | PC6 | PC5 | PC4 | PC3 | PC2 | PC1 |
+-----+-----+-----+-----+-----+-----+-----+-----+

+-----------------------------------------------+
|          (PINC >> PC1) & 0b00000011           |
+-----+-----+-----+-----+-----+-----+-----+-----+
|  0  |  0  |  0  |  0  |  0  |  0  | PC2 | PC1 |
+-----+-----+-----+-----+-----+-----+-----+-----+

So the result is 0 if PC1 and PC2 are low, 1 if only PC1 is high, 2 if only PC2 is high, or 3 if they're both high.

September 16, 2010
by sonierm
sonierm's Avatar

Hello,

I have tried both of your codes, they both handle direction quite well! The only problem is they are both incrementing by 4 per notch on the encoder.

Thanks for all your help!

September 16, 2010
by bretm
bretm's Avatar

That's pretty common. They call them QUADrature encoders for a reason. ^_^ This sophisticated piece of code should take care of the problem:

int notches = count / 4;

Or maybe this:

uint8_t oldPos = previousPos;
uint8_t newState = (PINC >> PC1) & 0b11;      // get both PC2 and PC1
uint8_t newPos = newState ^ (newState >> 1);  // undo Grey code
previousPos = newPos;

if (newPos == 0) // completed all 4 quadrants
{
    if (oldPos == 3)
        count++;
    else if (oldPos == 1)
        count--;
}
September 17, 2010
by Ralphxyz
Ralphxyz's Avatar

sonierm. please post your working code for your whole project either here in the forumn or possible at pastebin. This discussion about using a encoder intrigued me so much I just had to get one, now I have to see what I can/could do with it.

Ralph

November 06, 2010
by sonierm
sonierm's Avatar

@Ralphxyz Here is the code for the encoder...sorry about the late reply

ISR(PCINT1_vect)
{
    uint8_t oldState = previousState;
    uint8_t newState = (PINC >> PC1) & 0b11;   // get both PC2 and PC1
    previousState = newState;
    uint8_t changedBits = oldState ^ newState;

    if (!((changedBits == 0b00) || (changedBits == 0b11))) //only runs if theres a change
    {
       if (oldState == 0)
       {
           count += ((newState == 1) ? +1 : -1);
       }
       if (count > 100)
       {
         count = 100;
       }
       else if(count < 50)
      {
          count = 50;
      }
   }

I am now trying to make a IR temp sensor work. I got a start on it based of the keyboard tutorial. The sensor has a clock and data line just like the keyboard. This is the data it sends:

0xddmmllccee

dd = internal or external temp label(0x4c=external temp,0x66 internal temp) mm = temperature msb ll = temperature lsb cc = check-sum (cc=dd+mm+ll) ee = end of line?(always seems to be 0x0D)

temperature (in Kelvin) = 0xmmll / 16

Heres some code i was tying,

if(!(PINC & (1<<PC4)))
{
  //clk was low
  //ready += 1;
  if(bit_count < 5)
  {
     if(PINC & (1<<PC3)){
        if(dd == 0) dd |= (1<<bit_count);
        else if(mm == 0) mm |= (1<<bit_count);
        else if(ll == 0) ll |= (1<<bit_count);
        else if(cc == 0) cc |= (1<<bit_count);
        else if(ee == 0) ee |= (1<<bit_count);
        else
        {
           if(cc == (dd+mm+ll)) ready = 1;
           dd |= (1<<bit_count);
           mm = 0;
           ll = 0;
           cc = 0;
           ee = 0;
        }
     }
     bit_count++;
  }
  else
  {
      bit_count = 0;
  }
}

So i am not quite sure how to get the data in all separate bytes like that, the code above dosnt actually work and im not sure why.

everyones help is always appreciated! Matt

November 07, 2010
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Hi Matt,

I think there's confusion about bits and bytes, at least with variable labels. It appears that you're trying to read 5 bytes, each of which has 8 bits, for 40 bits total. Is that correct? And PC4 is clock in, and PC3 is data in? Is this code within a Pin Change Interrupt like the PS/2 Keyboard example?

The next question is, for each of the 5 bytes, is the MSB sent first, or is the LSB sent first? (For example, UART and PS/2 use LSB-first, while SPI uses MSB-first).

Also, if you have a link to the IR temp sensor datasheet, it'd probably help us know what you're facing.

In any case, you might want to keep separate counters bit_count (0..7) and byte_count (0..4), to keep track of where you are in receiving data from the sensor.

Hope that helps!

Mike

November 07, 2010
by sonierm
sonierm's Avatar

Hey Mike, Yes the code is within the pin change interrupt.

Here is the product http://www.sparkfun.com/commerce/product_info.php?products_id=86

The only information I have is from a comment:

Yes this unit can be easily connected to a micro-controller

Pin out:
A-activate (pulse low to take a reading, or keep low to read continuously)
D-Data out
C-Clock (read data bit on falling edge)
G-GND
V-power (I used 3.3vdc not sure what the limits are)

Data string:
it outputs 5 bytes of data:

0xddmmllccee

dd = internal or external temp label(0x4c=external temp,0x66 internal temp)
mm = temperature msb
ll = temperature lsb
cc = check-sum (cc=dd+mm+ll)
ee = end of line?(always seems to be 0x0D)

temperature (in Kelvin) = 0xmmll / 16

Yes Pc 4 is clock and Pc3 is data

"Is the MSB sent first, or is the LSB sent first?" I have no idea

November 08, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi sonierm,

I think the bigger thing to get straight (before LSB vs MSB) the issue Mike pointed about bits vs bytes in your code. Your device will send a total of 5 bytes of data, each of which will contain 8 bites of transmitted data. I suggest restructuring your loop to look more like this.

uint8_t data[5]; //0xddmmllccee
uint8_t bytecount;
uint8_t bitcount;

ISR(pin_change_interrupt){
  if(clock_direction_right){
    if(data_pin_high){ //set bit to one
       data[bytecount] = data[bytecount] | (1<<bitcount);
    }
    //increase bitcount
    //make sure bitcount rolls back to 0 after reaching 7
    //increment bytecount when bitcount rolls over
    //if bytecount is 4 and just read the 7th bit, check the checksum, reset everything
    //back to 0.

  }
}

Once you are loading all the data into your 5 bytes you can print them out to the LCD and it should be fairly straight forward to see if it is coming in LSB first or MSB first. If what you are getting doesn't make sense just switch the direction you are loading the data into the array. I would suggest just ignoring the checksum step for now until you figure that part out.

Hope that makes sense, let me know if you have any questions.

Humberto

November 08, 2010
by sonierm
sonierm's Avatar

Ok so heres the code that has 5 bytes of 8 bits

    if(!ready)
    {
       if(!(PINC & (1<<PC4)))
       {
         if(bit_count < 8)
         {
            if(PINC & (1<<PC3))
            {
               data[byte_count] = data[byte_count] | (1<<bit_count);
               bit_count++;
            }
         }
         else
         {
             bit_count = 0;
             byte_count += 1;
             if(byte_count > 4)
             {
               byte_count = 0;
               ready = 1;
             }
         }
       }
    }

So i printed data[0] data[1] data[2] in hex out to the lcd and they all quickly go to FF, not sure why...maybe im giving it on byte to much? also you say "clock_direction_right" how is that done? do I need to remember its previous state to ensure it was a falling edge and not an end of the clock signal? (if that even makes sense)

November 09, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi sonierm,

I think you want to move the bit_count++ outside the if(PINC & (1<<PC3). Currently you do not increase the bitcount until after the current bit gets set to 1, you want to leave the bit at 0 should the pin be low when the clock edge triggers your interrupt.

The way you have your if else setup at the moment is also going to cause you to miss the first bit out of every byte. Remember that every time your interrupt fires you have a new bit coming in. If your bitcount is 8 or more it goes to the else statement to do the rollovers, but it ignores the bit that just came in. You will need to rework the logic a little bit.

I think you are doing the "clock_direction_right" correctly at the moment. Remember your interrupt should only be triggered when there is a change of state on the pin. Since there are only two possible states for it, if you check for a low state of the pin within the interrupt you are reasonably sure the line just transitioned from high to low. Note that that is not necessarily the case if you spend too much time in the interrupt and the interrupt calls start running into each other.

Humberto

November 09, 2010
by sonierm
sonierm's Avatar

okay heres new code

if(!ready)
{
   if(!(PINC & (1<<PC4)))
   {
     bit_count++;
     if(bit_count >= 8)
     {
         bit_count = 0;
         byte_count += 1;
         if(byte_count > 4)
         {
           byte_count = 0;
           ready = 1;
         }
     }
     //bit_count++;
     if(PINC & (1<<PC3))
     {
        data[byte_count] = data[byte_count] | (1<<bit_count);
     }
   }
}

I am actually getting data now but nothing seams correct, for example i got 6590B63860 thats a temp of over 2000kelvin when it should be about 280-300K

What do you think the problem is now? I have tried several different things and nothing is getting proper data

November 09, 2010
by bretm
bretm's Avatar

When PC4 goes low, that's the clock edge you need? Where do you wait for PC4 to go high again?

Can you just hook this up to the SPI pins? This is exactly what SPI is for. SPI reads 8 bits at a time and handles the clock for you. It supports rising or falling clock edge modes.

Once you set up SPI slave mode, wait for the SPIF bit of SPSR to go high and then read the byte from SPDR. Do this five times. The data-sheet has code samples for SPI_SlaveInit and SPI_SlaveReceive. Be sure to read the paragraph before the samples which explains what DDR_SPI, DD_MOSI, DD_MISO and DD_SCK are.

November 10, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi sonierm,

You are definitely getting closer, but I think there is still a logic issue in your code. The first time this fires, bitcount is incremented. So the first bit actually ends up in the first position, not the 0th position. I think if you move the final if statement to the top you might see better results. Keep in mind that you are not sure if these are coming MSB first or LSB first, so you might need to write out the bits you are getting and flip them to see if they make more sense that way.

bretm mentioned you can use the SPI bus to help you with this logic. That is definitely true, and it might be something you consider doing as an optimisation for your program, but I hope you are enjoying (and learning from) coding the receiving end of a clocked protocol like this one.

Humberto

November 10, 2010
by sonierm
sonierm's Avatar

Okay getting much better results with this

if(!(PINC & (1<<PC4)))
{
  if(PINC & (1<<PC3))
  {
     data[byte_count] = data[byte_count] | (1<<(7- bit_count));
  }
  bit_count++;
  if(bit_count > 7)
  {
     bit_count = 0;
     byte_count += 1;
     if(byte_count > 4)
     {
        byte_count = 0;
        ready = 1;
     }
  }
}

Still have a few problems, I might try the SPI bus

Right now, its outputting the temp in kelvin to the lcd. The temp is accurate within a few degrees. If I point it at something hot, the temp goes up on the lcd and the built in lcd on the gun but when i move it away, it dosnt come back down on the lcd (it does on the built in one tho)

Heres the code that sets the temp

     if(ready)
     {
        if(data[1] == 0 && data[2] == 0) continue;
        temperature = 0;
        temperature = (((data[1] * 255)+ data[2])/16);
        ready = 0;
     }

Also when I was outputting the 5 bytes to the LCD i was getting a very odd first byte...like 76 and other odd values. I think this is but my check sum is never off my much...I think it is not reading the first bit properly.

I will try more tomorrow and maybe attempt the SPI bus implementation. You guys have been of great help. cheers

November 20, 2011
by NSNR8R
NSNR8R's Avatar

Hello,

If anyone is still watching this thread, is there any way to detect each pulse from the encoder or must the state change be detected inside of a loop? I am using a 4096 CPR optical encoder. Even very small changes in position results in a state change that is too fast to be detected using a polling method.

Thanks, David

November 21, 2011
by Ralphxyz
Ralphxyz's Avatar

So David could you use a interrupt?

I can see why a polling method might be to slow especially if you are doing anything else besides poling but an interrupt should be fast enough to catch the output of the encoder.

Ralph

November 21, 2011
by NSNR8R
NSNR8R's Avatar

Thanks Ralph, This was the firt project that I attempted other than minor modifications to the tempsensor project. I was not understanding interrupts and had not enabled them. This seems to work:

volatile uint8_t previousState;
volatile uint16_t count;

ISR(PCINT1_vect)
{

    uint8_t oldState = previousState;
    uint8_t newState = (PINC >> PC1) & 0b11;   // get both PC2 and PC1
    previousState = newState;
    uint8_t changedBits = oldState ^ newState;

    if (!((changedBits == 0b00) || (changedBits == 0b11))) //only runs if theres a change
    {
       if (oldState == 0)
       {
           count += ((newState == 1) ? +1 : -1);
       }
       if (count >4096)
       {
         count = 1;
       }
       else if(count < 1)
      {
          count = 4096;
      }
   } 
}
int main() {
  // start up the LCD
  lcd_init();
   // activate interrupts
 PCMSK1 = (1<<PCINT9) | (1<<PCINT10);//Un-mask PCINT9    
 PCICR = (1<<PCIE1);//Enable the PORTC pin change interrupt
 sei();
\\Code to display count on LCD
}

Thanks, David

November 21, 2011
by Ralphxyz
Ralphxyz's Avatar

All right David, way to go.

To go from minor modifications to the temp sensor project to using a interrupt is a major accomplishment.

Ralph

November 22, 2011
by Ralphxyz
Ralphxyz's Avatar

I know, I know, that should be an interrupt not a interrupt, geesch!

But I still think David did a great job comprehending interrupts this early.

Ralph

Post a Reply

Please log in to post a reply.

Did you know that interrupts can cause problems if you're not careful about timing and memory access? Learn more...