Suggestions on how to make Blinky blink

Go To Last Post
31 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greetings to the Freakin' Crew....

 

Straight away this is an existing commercial product I designed several years ago that a new feature has been asked to be added.

 

Background, I have an air pressure sensor that outputs a 14 bit reading via I2C.  These readings are stored in an AVR until the host polls the device and once the transfer is done it sits in a holding pattern waiting to be polled again.  Nothing to impressive.....

 

When the customer needs to change the air pressure in the line, they have to connect a gauge and then turn a small screw in my device to change the inline pressure.  Problem is that this is sometimes not so simple as the gauge is not nearby.

 

The solutions is to load the desired pressure reading in EEPROM and flash a small LED I have on the unit in response to the setscrew point.  Once the pressure is within a certain 'window' the led will illuminate solid and when the pressure goes above the window, the blinking will continue faster and faster.

 

My thought was to blink the LED at a frequency between 0Hz and 10 Hz.  The blink rate does not need to be entirely linear as long as the led blinking goes faster and faster as the pressure climbs higher and higher.  Still sounds simple enough,  Since this is a window comparator type thing, I will have the upper and lower limits stored in the CPU to compare the pressure readings to.

 

Heres the thing, the sensor is taking readings  faster than the led can blink.  Meaning that a simple timer compare setup toggling the led will not respond fast enough to the user turning the screw and the sensor sending out the data.  Even though there is a 'window' its not very large and it would be very easy to miss one of the limits.

 

So I am looking for some suggestions on how to tighten the LED blink rate update to the sensor read speed.  Waiting for the LED blink to finish a cycle before taking a reading is not practical.  I have thought about using multiple:

 if((pressure > x) and (pressure <= y)){Blink this fast}

But thats a lot of if() statements.

Another option I am toying with is to either Vary TCNT or OCRx.

 

Any suggestions are certainly welcome. 

 

JIm

This topic has a solution.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Mon. Feb 11, 2019 - 09:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  • Maintain a systick (1 ms, or whatever you otherwise need)
  • Track the last time the LED changed state (ON->OFF or OFF->ON)
  • With each sensor sample, compute the desired toggle period (which will be half the flash period)
  • Compute delta of current systick with the recorded last LED state change
  • If the delta is greater than computed desired toggle period, toggle the LED and record the time

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks.

 

I am going to have to sleep on that one as its a little late to wrap my head around it.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's some example code (untested):

last_toggle_ms = 0;
.
.
.
while (1) {
  .
  .
  .
  pressure = sample_pressure();
  period_ms = compute_half_period_for_led(pressure);
  now = millis();
  if ((now - last_toggle_ms) >= period_ms) {
    toggle_led();
    last_toggle_ms = now;
  }
  .
  .
  .
}
    

Types will depend on your systick type.  Note that I usually use milliseconds as my systick unless I have a good reason not to.

 

Special attention may be needed to handle overflow, edge cases, etc., but this should demonstrate the intent.  Basically, the LED can be toggled at any time because the computed toggle period is recomputed after every sample taken, and then the comparison against the elapsed period determines whether or not to toggle.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reviewing customer's requirements, is there any special reason for not using a display instead of LED?
.
I think displaying absolute value such as exact pressure value or a percentage of value in the form of digits are more definite and user friendly,
"slow blink" or "fast blink" are relative expresions and depends on the judgment of users and may increase the ambiguity.

Majid

Last Edited: Sun. Feb 10, 2019 - 10:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

m.majid wrote:

Reviewing customer's requirements, is there any special reason for not using a display instead of LED?

 

jgmdesign wrote:

When the customer needs to change the air pressure in the line, they have to connect a gauge and then turn a small screw in my device to change the inline pressure.  Problem is that this is sometimes not so simple as the gauge is not nearby.

 

It would appear that Jim has chosen an LED so that it can be seen at a distance. Unless the display is very big.........

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I really don't get this.

 

Is your device really as simple as a I2C bridge to some undisclosed host ?

If so what on earth does the set screw do ?

 

Who is controlling the compressor / solenoid valve to regulate the pressure ?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:

m.majid wrote:

Reviewing customer's requirements, is there any special reason for not using a display instead of LED?

 

jgmdesign wrote:

When the customer needs to change the air pressure in the line, they have to connect a gauge and then turn a small screw in my device to change the inline pressure.  Problem is that this is sometimes not so simple as the gauge is not nearby.

 

It would appear that Jim has chosen an LED so that it can be seen at a distance. Unless the display is very big.........

 

As I wrote in my OP:

jgmdesign wrote:
The solutions is to load the desired pressure reading in EEPROM and flash a small LED I have on the unit in response to the setscrew point.

 

There is an existing LED on the unit.  And there is no redesigning the device for a display that will not be used very often.

 

N.Winterbottom wrote:
I really don't get this. Is your device really as simple as a I2C bridge to some undisclosed host ? If so what on earth does the set screw do ? Who is controlling the compressor / solenoid valve to regulate the pressure ?

 

Its not relevant, but short answer is yes it is essentially an I2C to host bridge, but there is a regulator built into the extruded aluminum housing to regulate air pressure.  Hence the setscrew.  I had nothing to do with that part.  Only the sensor. 

 

@joey

Thanks for the example code.  I'll write up a small test program to get it working before trying to integrate it into the actual device source.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The number (just a byte) to be communicated between

threads is the time between the next two toggles.

If the transmitting thread is fast enough,

some transmitted bytes will go unused.

I do not see a problem with that.

 

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How about an alternative approach.

 

Can you swap out the LED in the unit for another LED?

 

If this is a software only update, then ignore the rest of this.

 

If swapping out the traditional LED for one of the WS2812B digital LEDs is an option, then read on.

 

Swap out the LED, the fancy digital one still only needs one I/O pin.

 

In your Loop if the pressure is too high, make the LED Red.

If the pressure is too low, make the LED blue or white or whatever.

If the pressure is just right, then make the LED green.

 

If the User is twisting the set screw too fast, it really doesn't matter.

Within two updates the new (over-shoot) color, be it high or low, will be displayed.

The User then knows that they have gone too far twisting the set screw, and they have to back it up a smidge.

 

When they (finally) get it right, they'll have a steady green LED as their reward/indication.

 

Snip, Snip...

Sounds like an office procedure.

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Doc,

No, the LED is integrated into a pushbutton.  The approach to its operation in the OP is what I need to make happen as it's the simplest to use(in operation).  A search for the same button with a red/green led came up a dead end.  SO what I have is what I have and thats all I have.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
Basically, the LED can be toggled at any time because the computed toggle period is recomputed after every sample taken, and then the comparison against the elapsed period determines whether or not to toggle.

Joey,

I took out some paper and pencil and started working out your description and from what I have on paper the only time the led will blink is if the pressure increases each time the sensor is sampled.  if the pressure stays the same, or decreases the led will not toggle.  Unless I am missing something....entirely possible.

 

I went with a 1Hz to 10Hz flash rate so a reading of 0 gives me 1Hz and 16384 gives me 10Hz.

 

In my paper notes I have a 1ms timer that increases a variable by 1 on every tick.  When the variable overflows it simply starts back at 0.  Not sure if I need to reset this in your example.

 

TO get my half period, I divide the sensor reading by 327.  anything lower on the reading I will simply ignore.  so for a reading of 16,383 I get about 50.100 (rounded to 50) do half period is 50ms

 

TO retrieve NOW, I simply read whats in the tick variable

 

 

If NOW is less than the last toggle ms then I get a negative number

 

If the new pressure is less than the previous reading I get no toggle, and it appears that it could be a long wait for the variable to reset back to satisfy your IF statement.

 

More pencil and paperwork to do.

 

JIm

 

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
If NOW is less than the last toggle ms then I get a negative number If the new pressure is less than the previous reading I get no toggle, and it appears that it could be a long wait for the variable to reset back to satisfy your IF statement.
This 'trick' (not really) is to compute (now - last_toggle_ms), and compare the result of that to the computed half-period for the LED.  If now and last_toggle_ms are the same unsigned type, the result will also be unsigned, and therefore always positive.

 

Imagine a 16-bit tick, so 0-65,535 ms.  Next imagine that the most recent toggle was at 65,530 ms.  Now imagine that ten ticks later, the current systick rolls over and ends up at 4.  So the expression (now - last_toggle_ms) is the expression (4 - 65530).  As you noted, this is negative.  However, since both operands are unsigned, so is the results of the expression.  Recall numerous threads on integer promotion and signedness.  The negative value is "converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type."  So although 4-65,530 as a signed result is -65,526, the value 65,536 is added, and we get 10... exactly what you would expect.  You don't have to do this addition.  In fact, neither does the compiler, nor the hardware.  It is simply a means for the standard to define the behaviour of two's complement arithmetic overflow and underflow.

 

jgmdesign wrote:
if the pressure stays the same, or decreases the led will not toggle.
It should work as advertised.  If the pressure stays the same, then the computed LED period stays the same.  Time, however, marches on.  With each pressure sample (though identical to the last), the delta between the current time and the time the LED was last toggled still increases.  When that delta exceeds the computed half-period, you toggle the LED and store the new last-toggled time.

 

EDIT:  typo

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Wed. Feb 13, 2019 - 04:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
Imagine a 16-bit tick, so 0-65,535 ms.

 

I think that's where I left the path.  I wasnt thinking about the size of the tick variable.  a 16 bit variable does put some things into perspective.  Getting late here and I have an early day so I will get back on this first thing in the moring

 

joeymorin wrote:
Recall numerous threads on integer promotion and signedness.

yes and no.  I will hit the search bar in the morning.

 

Thanks for the clarification!

 

joeymorin wrote:
It should work as advertised.

Not doubting you.  Will hit this in the am.

 

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
TO get my half period, I divide the sensor reading by 327
If you want the sensor range of 0-16,383 to translate to 1 to 10 Hz, then yes you want the 16,383 to translate to 50 ms for a full-period of 100 ms, but dividing by 327 won't get you that.  Or rather, it will for the max sensor value, but for lower sensor values the half-period will be shorter, meaning the frequency will be higher than 10 Hz, the opposite of what you're after.

 

A sensor value of 16,383 maps to an LED frequency of 10 Hz, which is a half-period of 50 ms.

A sensor value of 0 maps to an LED frequency of 1 Hz, which is a half-period of 500 ms.

 

Maybe the simplest approach is to just do a simple linear transformation:

int32_t map(
    const int32_t x,
    const int32_t in_min,
    const int32_t in_max,
    const int32_t out_min,
    const int32_t out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Then you call it something like:

    half_period = map(pressure, 0, 16383, 500, 50);

 

I've tested my suggested approach in #2 and #4 with an LED and a pot as a substitute sensor, and it works as expected.  With a 500 ms period it's a little hard to throw the pot from one end to the other at the right time to see the LED half-period foreshortened, but if I change the range to 0.1 Hz - 10 Hz (5000 ms - 50 ms), then it's a little more obvious.

 

Note that the map() function returns a signed integer, and it's arguments are signed as well (this is necessary to handle negative-slope linear transformations such as yours).  Either assign it to an unsigned variable, or cast it to an unsigned type before using it in the comparison expression in the if().

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Mon. Feb 11, 2019 - 06:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
There is an existing LED on the unit.  And there is no redesigning the device for a display that will not be used very often.

OK,

It is possible to add an OLED dsipaly without redesigning the PCB if :
- your current PCB design already has ISP programming socket (MISO,+5,SCK,MOSI,RST,GND), and MISO,SCK,MOSI are not used yet and can be used for OLED display

- case / box of device has additional space for OLED display.

- there is 4-5 kbyte spare blank flash

- there is 20-30mA spare current of Vcc

- customer accepts the additional costs for OLED display

 

if the only interface is 1 LED, an alternative method would be "pulse and delay" 

so that for each value N=1 to 10, LED blinks in a fixed frequency (4 Hz, 100ms ON, 150ms OFF) N times, then stay OFF for 1 second as break,

for example

N=1 :

/\_______________________/\_______________________ ...

 

N=2 :

/\___/\_______________________/\___/\_______________________ ...

 

...

 

N=10 :

/\___/\___/\___/\___/\___/\___/\___/\___/\___/\_______________________/\___/\___/\___/\___/\___/\___/\___/\___/\___/\_______________________ ...

 

the advantage is user can easily count the pulse and understand the exact value

disadvantage is user have to wait a few seconds to read the adjusted value (for N=10 : 2.5s pulses + 1s break = 3.5s)

Majid

Last Edited: Mon. Feb 11, 2019 - 08:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

m.majid wrote:

...an alternative method would be "pulse and delay" so that for each value N=1 to 10, LED blinks in a fixed frequency (4 Hz, 100ms ON, 150ms OFF) N times, then stay OFF for 1 second as break,

...disadvantage is user have to wait a few seconds to read the adjusted value (for N=10 : 2.5s pulses + 1s break = 3.5s)

 

You might want to prototype something like that for yourself and see how interactive it is (hint - it isn't). Study after study shows that once the delay between the 'action' and the 'reaction' exceeds 100ms then the system is seen as unresponsive, and systems that require interactive adjustments become unusable.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you can , put a beeper over the LED, and make a solid sound when ok, and ticks when not (where off time gets bigger with the error). 

(or the other way no sound if ok)

 

 

You hear faster than you see :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The blinky thread goes something like this:

if(time has passed toggle_time) {
    toggle();
    toggle_time+=half_period; 
}

The sensor thread updates half_period.

If the blinky thread is actually an ISR,

toggle_time is an IO register and the if can be omitted.

The speed at which the senser thread can

update half_period does not matter much.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
    toggle_time+=half_period; 

Although that's what I usually do, it may not be appropriate here.  If the user makes a fast adjustment, then it might take multiple += operations to 'catch up'.  The result is a number of (too) fast toggles.  Instead:

    toggle_time = now; 

May not matter given the range of values suggested by the OP, as the catch-up time is likely to be very short.

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well this seems to be a working solution thanks to Joey!

 

Taking his examples and adding some of my own code I came up with this:

/*
 * variable blinky.c
 *
 * Created: 2/11/2019 9:30:03 AM
 * Author : jgmDESIGNS
 */ 

#define F_CPU 12000000ul
#include <avr/io.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>

volatile uint16_t tick;
uint16_t last_toggle_ms;
volatile uint16_t pressure;
uint16_t period_ms;
uint16_t now;

// Voltage Reference: AVCC pin
#define ADC_VREF_TYPE ((0<<REFS1) | (1<<REFS0) | (0<<ADLAR))



//interrupts
ISR(TIMER0_OVF_vect)
{
	// Reinitialize Timer 0 value
	TCNT0=0x44;
	tick++;		//increase tick counter by one
	// Place your code here

}

ISR(ADC_vect)
{
	pressure = ADC;	//read ADC result into pressure variable
}

void avr_init(void)
{
	// Port D initialization
	// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
	DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (1<<DDD0);
	// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
	PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (1<<PORTD0);
	
	// Timer/Counter 0 initialization
	// Clock source: System Clock
	// Clock value: 187.500 kHz
	// Mode: Normal top=0xFF
	// OC0A output: Disconnected
	// OC0B output: Disconnected
	// Timer Period: 1.0027 ms
	TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
	TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
	TCNT0=0x44;
	OCR0A=0x00;
	OCR0B=0x00;
	
	// ADC initialization
	// ADC Clock frequency: 750.000 kHz
	// ADC Voltage Reference: AVCC pin
	// ADC Auto Trigger Source: Free Running
	// Digital input buffers on ADC0: Off, ADC1: On, ADC2: On, ADC3: On
	// ADC4: On, ADC5: On
	DIDR0=(0<<ADC5D) | (0<<ADC4D) | (0<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (1<<ADC0D);
	ADMUX=ADC_VREF_TYPE;
	ADCSRA=(1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);
	ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
	
	// Timer/Counter 0 Interrupt(s) initialization
	TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (1<<TOIE0);
	
	
}

int32_t map(const int32_t x, const int32_t in_min, const int32_t in_max, const int32_t out_min, const int32_t out_max)
{
	uint16_t y = x*16;    //used this to get 14 bit result as avr ADC only goes as high as 1023 <--FOR TESTING ONLY!!
	return (y - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void toggle_led(void)
{
	PORTD = PORTD ^ 0x01;	//just flip bit 0 of port d
}

int main(void)
{
	tick = 0;	//reset tick count
	last_toggle_ms = 0;	//reset toggle
	period_ms = 0;	//reset period
	now = 0;	//reset now
	
	avr_init();	//setup the avr
	
	sei();
	
	//start the ADC before entering loop
	ADCSRA = ADCSRA | (1<<ADSC);
	
    /* Replace with your application code */
    while (1) 
    {
		period_ms = map(pressure, 0, 16383, 500, 50);
		now = tick;
		if ((now - last_toggle_ms) >= period_ms) {
			toggle_led();
			last_toggle_ms = now;
		}
    }
}

not the greatest style, and not much commenting, but this code seems to do what I am looking for as far as blinky goes! smiley

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You'll want to access tick atomically, otherwise you might get the odd 'corruption' in the delta time expression.

 

#include <util/atomic.h>
.
.
.
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    		now = tick;
        }
.
.
.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

You'll want to access tick atomically, otherwise you might get the odd 'corruption' in the delta time expression.

 

#include <util/atomic.h>
.
.
.
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    		now = tick;
        }
.
.
.

 

Question on this.  I made some other changes for functionality where I reset tick to zero.  Long story/not important.  Code still works fine.  the question is, do I need to do an atomic access to tick every time I want to use it?

 

Example, a WHILE loop:

while(tick <= 15000)
{
    //do something
}

I can understand why the need for Atomic read for updating 'now'.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:

Question on this.  I made some other changes for functionality where I reset tick to zero.  Long story/not important.  Code still works fine.  the question is, do I need to do an atomic access to tick every time I want to use it?

 

Example, a WHILE loop:

while(tick <= 15000)
{
    //do something
}

I can understand why the need for Atomic read for updating 'now'.

Jim

I would, as a matter of habit.  Any access to tick may happen at an 'edge case', where both bytes of tick are being updated in the ISR.  Thus when tick gets updated from 0x00FF to 0x0100 you might access high(tick) and get 00, then the ISR updates, then low(tick) and get 00, so your corrupt version of tick is 0x0000, not 0x0100.  If the access happens in reverse order you can get 0x01FF rather than 0x0100.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Short answer, yes:

while (1)
{
    typeof(tick) tick_local;
    ATOMIC_BLOCK(RESTORE_STATE)
    {
        tick_local = tick;
    }
    if (tick_local <= 15000)
    {
        //do something
    }
    else
    {
        break;
    }
}

 

Long answer, if you can otherwise guarantee that tick will not be accessed by the other thread, no.  The use of ATOMIC_BLOCK() is a conventional way to make that guarantee.

 

For your example of <= 15000, imagine that tick currently has a value of 14847.  That's a hexadecimal value of 0x39FF.  Now your code begins to evaluate the conditional expression (tick <= 15000) by reading the 16-bit tick.  It does so by first reading the low byte into a register, and that's 0xFF.  Now the timer interrupt breaks in and increments the 16-bit value by one, leaving it as 0x3A00 and then returning to the point of interruption.  That point is where your code left off, and the next thing it does is read the high byte of tick, which is now 0x3A.  The combined read value of tick is 0x3AFF, or 15103 decimal.  That is not <= 15000, so the while() loop exits prematurely, since the actual time is 14848.  In effect, the loop was exited 152 ms early.  Whether or not this is a problem for your code, only you can answer.  It may not cause a problem locally, but the 152 ms offset could have a knock-on effect to later code.  Again, only you can answer that.
 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks both of you for the feedback.

 

While the loop exiting 152ms early is not an issue, in the interests of getting into the habit of proper coding I will change the application and take it for a test flight.  In the grand scheme, an IF() essentially behaves like a WHILE() and vice versa in cases like this.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Solution is Posts #2, #4, and #15. 

 

Thank you Joey,

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pressure is not accessed atomically nor is it initialised.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Pressure is not accessed atomically nor is it initialised.
Good catch.  I hadn't looked carefully enough at the code to see that the ADC was being handled via interrupt.

 

The code in #21 is just a test with a pot standing in for the I2C pressure sensor, but it bears mentioning in case the real app code suffers from a similar issue.

 

In my own test code I simply polled ADSC and fetched ADC in the main thread.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Pressure is not accessed atomically nor is it initialised.

 

joeymorin wrote:
The code in #21 is just a test with a pot standing in for the I2C pressure sensor, but it bears mentioning in case the real app code suffers from a similar issue.

 

Correct.  In the actual application the sensor is not free running so it will not be an issue, but I agree....Good Catch!!

 

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

just call me Lint-man!