Go Down

Topic: Serial print refresh time (Read 3274 times) previous topic - next topic

jtw11

May 25, 2012, 05:20 pm Last Edit: May 25, 2012, 05:24 pm by jtw11 Reason: 1
Hi guys,

Had an Arduino (Uno) for a while now, but never used these forums. I've got a simple sketch reading the output of an LM35 temp sensor to define the PWM duty cycle of an output to control a fan. I'm also outputting the temperature via serial to the serial monitor. I've got a delay(200) at the end of the loop so that the temp is only sent once every 1/4s, however - I've just noticed, this is holding up the entire loop for that time too.

Now - I'm well aware temp sensors take a while to respond, and so waiting such a time isn't actually a problem here at all, the system responds perfectly well... but, for future reference - how do I send the temp via serial at set intervals, yet not hold up the rest of the loop from, well - looping again!

Furthermore, as you can see in the code - I've got the temp, and "deg C" on two different prints, followed by a blank println - how can I get these two little snippets to appear on the same line in the serial monitor, with one line of code. I thought maybe Serial.println(temp, "deg C"); may work, but not so.

Many thanks in advance!

Code: [Select]
int tempPin = 1; // defines the LM35 input into analogue pin 1
int valFan = 0; // creates an integer used for temperature mapping, this being mapped fan speed - default to 0
int fanPin = 9; // defines the fan output connected to digital pin 5
int onboardLED = 13;

void setup()
{
 analogReference(INTERNAL); // sets ADC ref voltage to internal 1.1v to increase resolution
 pinMode(fanPin, OUTPUT); // defines fanPin as an output
 pinMode(onboardLED, OUTPUT); // defines onboardLED as an output
 digitalWrite(onboardLED, LOW); // turns off onboard pin 13 LED
 Serial.begin(9600); // initialises serial comms at 9600 baud rate
 digitalWrite(fanPin, HIGH); // pulses fan output to max
 delay(250); // waits 250ms
 digitalWrite(fanPin, LOW); // then switches output to fan off before commencing loop, helps to kickstart sticky fans into motion at low PWM duty cycles
}

void loop()
{
 valFan = map(analogRead(tempPin), 0, 500, 0, 255); // used to map valFan between 0 and 255 for PWM, between 2 and 55 degrees C (LM35 output = 0v @ 2deg C, + 10mV/degC)
 valFan = constrain(valFan, 0, 255); // sets limits of valFan
 analogWrite(fanPin, valFan); // write PWM to fanPin
 int temp = (1.1 * analogRead(tempPin) * 100 / 1024); // converts analog reading into degrees C
 Serial.print(temp); // prints to serial monitor
 Serial.print(" deg C");
 Serial.println("");
   delay(200); // updates serial monitor every 200ms (+ miniscule execution time of the rest of the loop)
}

Arrch

#1
May 25, 2012, 05:23 pm Last Edit: May 25, 2012, 05:25 pm by Arrch Reason: 1
Check the blink without delay example to see how to perform an action at every given interval without using delay().


Furthermore, as you can see in the code - I've got the temp, and "deg C" on two different prints, followed by a blank println - how can I get these two little snippets to appear on the same line in the serial monitor, with one line of code. I thought maybe Serial.println(temp, "deg C"); may work, but not so.


Code: [Select]
Serial.print("This ");
Serial.print("prints on ");
Serial.println("the same line!");

jtw11


Code: [Select]
Serial.print("This ");
Serial.print("prints on ");
Serial.println("the same line!");



Sorry, the question was worded a little strange - what I meant is, using the code the way I've written it does print "32 deg C" for example on a fresh serial monitor line each time, I meant is there a command so that I can code it in one line, in the program, itself.

Arrch


Sorry, the question was worded a little strange - what I meant is, using the code the way I've written it does print "32 deg C" for example on a fresh serial monitor line each time, I meant is there a command so that I can code it in one line, in the program, itself.


sprintf() function will allow you to format a null terminated char array (string) with variables.

jtw11

Brilliant, just tested the new code without a delay (set serial output to 20 seconds for test) - and it everything else responds instantly. Thanks very much! Here's the code if you're interested. Will look into cleaning up the serial commands themselves though.

Code: [Select]
int tempPin = 1; // defines the LM35 input into analogue pin 1
int valFan = 0; // creates an integer used for temperature mapping, this being mapped fan speed - default to 0
int fanPin = 9; // defines the fan output connected to digital pin 5
int onboardLED = 13;
long previousMillis = 0;
long interval = 20000;

void setup()
{
  analogReference(INTERNAL); // sets ADC ref voltage to internal 1.1v to increase resolution
  pinMode(fanPin, OUTPUT); // defines fanPin as an output
  pinMode(onboardLED, OUTPUT); // defines onboardLED as an output
  digitalWrite(onboardLED, LOW); // turns off onboard pin 13 LED
  Serial.begin(9600); // initialises serial comms at 9600 baud rate
  digitalWrite(fanPin, HIGH); // pulses fan output to max
  delay(250); // waits 250ms
  digitalWrite(fanPin, LOW); // then switches output to fan off before commencing loop, helps to kickstart sticky fans into motion at low PWM duty cycles
}

void loop()
{
  valFan = map(analogRead(tempPin), 0, 500, 0, 255); // used to map valFan between 0 and 255 for PWM, between 2 and 55 degrees C (LM35 output = 0v @ 2deg C, + 10mV/degC)
  valFan = constrain(valFan, 0, 255); // sets limits of valFan
  analogWrite(fanPin, valFan); // write PWM to fanPin
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval)
  {
    previousMillis = currentMillis;
    int temp = (1.1 * analogRead(tempPin) * 100 / 1024); // converts analog reading into degrees C
    Serial.print(temp); // prints to serial monitor
    Serial.print(" deg C");
    Serial.println("");
  }
}

Arrch

Looks good.

As good practice, I would also make the pins and interval constants.

jtw11

#6
May 25, 2012, 06:35 pm Last Edit: May 25, 2012, 06:39 pm by jtw11 Reason: 1

Looks good.

As good practice, I would also make the pins and interval constants.


Sorry - not quite with you. Are you referring to the 'long interval = 20000"? ...and as for the pins?

Arrch


Sorry - not quite with you. Are you referring to the 'long interval = 20000"? ...and as for the pins?

Yes. It's not going to make a difference with your current code, but it's good practice to define them as constants if there is no plan to change them within the code.

jtw11

Hmm - nope, still not got it! :D

Do you mean, as opposed to 'long interval', write 'long const interval'? 'const interval' throws an error at me.

As for pins, what isn't quite best practice?

You'll have to excuse me - before Arduino, I had no experience whatsoever with any C variant.

Arrch


Do you mean, as opposed to 'long interval', write 'long const interval'? 'const interval' throws an error at me.

Code: [Select]

const unsigned long interval =

Quote
As for pins, what isn't quite best practice?

Not sure what you mean by that.

Something like:
Code: [Select]
const int tempPin = 5;
would be best practice. You could also change it to a short, but I don't know which way the compiler handles constant declaration, so I'm not sure if that's necessary.

jtw11

Ah okay, I see where you're coming from.

Quote
const int tempPin = 1; // defines the LM35 input into analogue pin 1
int valFan = 0; // creates an integer used for temperature mapping, this being mapped fan speed - default to 0
const int fanPin = 9; // defines the fan output connected to digital pin 5
const int onboardLED = 13;
long previousMillis = 0;
const unsigned long interval = 500;


What exactly is the benefit to defining pins and intervals in this way?

AWOL

If there are lots of references to them, there's only one place to change them if you decide to move a pin, or need a little longer to do something.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

jtw11


If there are lots of references to them, there's only one place to change them if you decide to move a pin, or need a little longer to do something.


I see what you're trying to say, but using 'int tempPin = 1;' for example, I simply reference tempPin in the program, and if I want to change the pin, I just change the 1 for something else.

So why, 'const int tempPin = 1;' instead of the old 'int tempPin = 1;'?

majenko

Quote
So why, 'const int tempPin = 1;' instead of the old 'int tempPin = 1;'?


The "const" tells the compiler the value will never change.  Therefore, instead of allocating a variable and taking up valuable RAM space, and slowing the system down reading and writing from RAM, it just uses the number "1".

It's functionally the same as

Code: [Select]

#define tempPin 1


but has the advantage that it is typecast to an int.

Arrch



If there are lots of references to them, there's only one place to change them if you decide to move a pin, or need a little longer to do something.


I see what you're trying to say, but using 'int tempPin = 1;' for example, I simply reference tempPin in the program, and if I want to change the pin, I just change the 1 for something else.

So why, 'const int tempPin = 1;' instead of the old 'int tempPin = 1;'?

If you mess up and change that value somewhere in your code, your code will still compile fine, but you're likely to see logic errors. By defining it as a constant, you're compiler will throw an error if you mess up and try and change the value in the code and it's A LOT easier to debug compiler errors than it is logic errors.

Go Up