UK
Offline
Edison Member
Karma: 44
Posts: 2212
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #15 on: May 25, 2012, 12:58:42 pm » |
Also, in reply to how to join your strings together into one print - you can use sprintf to build up a string before printing to serial: char buffer[80];
// ...
sprintf(buffer,"The temperature is %f degrees C", temperature);
Serial.println(buffer);
where %f is a placeholder for a "float" or "double" variable - there are others for other variable types - plenty of references online.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Sr. Member
Karma: 1
Posts: 313
|
 |
« Reply #16 on: May 25, 2012, 01:18:31 pm » |
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 #define tempPin 1
but has the advantage that it is typecast to an int. Aha, that's the explanation I was looking for! (thanks to everybody else too!) On that subject, are there any other ways to reduce the program size, as this sketch actually forms part of a complete automated engine dyno control program.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Edison Member
Karma: 44
Posts: 2212
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #17 on: May 25, 2012, 01:22:56 pm » |
are there any other ways to reduce the program size Yes. Write it in assembly instead of C++. But seriously, some tips: 1. Avoid float / double - the floating point library adds loads of bulk. 2. Don't use variables bigger than you need. The processor is 8-bit. Anything bigger than a BYTE or CHAR uses extra instructions to emulate a larger value. 3. Think about the flow of your program. Write it tight, and the resultant program will be tight.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Sr. Member
Karma: 1
Posts: 313
|
 |
« Reply #18 on: May 25, 2012, 02:56:12 pm » |
Having taken snippets and applied them for use in my code from the 'blink without delay' example, could somebody please explain to me the use of 'unsigned long' in place of 'int'? It seems 'int' takes up just a few bytes more, but I'm not sure what 'unsigned long' really is, or indeed why the example uses it. English please?  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;
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Edison Member
Karma: 44
Posts: 2212
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #19 on: May 25, 2012, 03:09:56 pm » |
The "const unsigned long" is just seen as (and takes up the room of) 500. However, when it's being used in comparisons, it's being combined with / compared against other values that are unsigned long. This just helps the compiler to know what it's doing so it doesn't get confused between different length variables. For example, if you subtract an int from a long, should the result be an int or a long? If you're putting it in a variable, then it's whatever the destination variable is cast as. If you're just using it as a comparison, what then? By telling the compiler it's an unsigned long, it's telling it that the value is of the same type as that returned by the millis() function. Unsigned long is twice as big (RAM wise) as an int. As it's a "const" though, it doesn't use RAM. Byte, char - 8 bits. Int, short - 16 bits. Long - 32 bits. Long long - 64 bits. (the "unsigned" doesn't affect the size, just the range of the content) Oh, and long previousMillis = 0;
should really be unsigned long previousMillis = 0;
to keep the signs the same.
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Sr. Member
Karma: 1
Posts: 313
|
 |
« Reply #20 on: May 25, 2012, 03:40:32 pm » |
Ah, I was just about to ask that question - one signed, one unsigned. So, I've changed them to both signed - but embarrassingly, I still don't understand the different between signed and unsigned, i'm aware one can contain neg values whilst the other can't. I can't sit here with a command in my code that I don't really know why it's there, even if it works. I completely understand why I've made some of 'const', so as to prevent the controller putting things in and out of RAM unnecessarily. I think maybe i'm confused between bytes, ints & longs. Which do I actually need to use here for the millis and intervals. I can't see why I need to sign, or unsign either. EDIT: Aha, the table on this page seems to explain it! http://www.cplusplus.com/doc/tutorial/variables/Well no, not really actually - because surely I can just use a 'short' instead, as the value is between 0 and 65535. Then signed or unsigned is simply a sign convention thing. Correct? All help up until now greatly appreciated!
|
|
|
|
« Last Edit: May 25, 2012, 03:55:38 pm by jtw11 »
|
Logged
|
|
|
|
|
California
Online
Edison Member
Karma: 40
Posts: 1861
|
 |
« Reply #21 on: May 25, 2012, 03:54:38 pm » |
Given two values unsigned short a = 0xD5; signed short b = 0xD5; a is interpreted as 213 b is interpreted as -43 This is important in comparison, multiplication, division operations as well as conversions for stuff like Serial prints because how it's interpreted would affect the result. Addition, subtraction and bitwise operations don't care as the result (in binary) is the same no matter how it's interpreted.
|
|
|
|
« Last Edit: May 25, 2012, 04:02:21 pm by Arrch »
|
Logged
|
|
|
|
|
UK
Offline
Sr. Member
Karma: 1
Posts: 313
|
 |
« Reply #22 on: May 25, 2012, 03:56:58 pm » |
Given two values unsigned short a = 0xD5; signed short b = 0xD5; a is interpreted as 211 b is interpreted as -43 Am I missing something here, where have the Ds come from?
|
|
|
|
|
Logged
|
|
|
|
|
California
Online
Edison Member
Karma: 40
Posts: 1861
|
 |
« Reply #23 on: May 25, 2012, 03:58:06 pm » |
Am I missing something here, where have the Ds come from?
0xD5 is the hex representation of 213 and -43. Edit: D5 is 213, not 211.
|
|
|
|
« Last Edit: May 25, 2012, 04:02:56 pm by Arrch »
|
Logged
|
|
|
|
|
Global Moderator
UK
Online
Brattain Member
Karma: 137
Posts: 19060
I don't think you connected the grounds, Dave.
|
 |
« Reply #24 on: May 25, 2012, 03:59:05 pm » |
The whole example is nonsense.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
New Hampshire
Offline
God Member
Karma: 13
Posts: 776
There are 10 kinds of people, those who know binary, and those who don't.
|
 |
« Reply #25 on: May 25, 2012, 04:07:15 pm » |
Ah, I was just about to ask that question - one signed, one unsigned. So, I've changed them to both signed - but embarrassingly, I still don't understand the different between signed and unsigned, i'm aware one can contain neg values whilst the other can't. I can't sit here with a command in my code that I don't really know why it's there, even if it works.
You should make them unsigned, not signed. millis() and micros() will never return a negative value. Look at the reference of a function to see it's return type. 9 times out of 10, that's the data type you want to store the value into. millis() and micros() return an unsigned long, so you should store the value in an unsigned long. Otherwise you will eventually run into problems. Both signed and unsigned long store their values in 4 bytes. So they have the same storage capacity, but they don't haverepresent the same range of values they can store. Because unsigned long only stores positive values, it can store twice as many positive values as signed long, because half of signed long's values are negative. A smaller scale example: byte is an 8 bit unsigned type, so it can store any value from 0 to 255. If you try to store the value 256 in it, you will get an overflow and the actual value stored in it will be 0. If you try to store 257 in it, the actual value stored will be 1. char is an 8 bit signed type. It stores values from -128 to to 127. It still has the same storage capacity, 256 discrete values, but a different range. However, if you have a function that returns a byte value, and you attempt to store it in a char, if that byte value is greater than 127, it will not be properly represented by the char type. The bit pattern will be stored exactly the same, but the representation will be different. Operations on the char value will likely have undesirable results.
|
|
|
|
« Last Edit: May 25, 2012, 04:18:50 pm by jraskell »
|
Logged
|
|
|
|
|
Global Moderator
UK
Online
Brattain Member
Karma: 137
Posts: 19060
I don't think you connected the grounds, Dave.
|
 |
« Reply #26 on: May 25, 2012, 04:10:58 pm » |
@Arch, You need to show how signed short b = 0xD5; gets sign extended to a negative number to -43.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
UK
Offline
Sr. Member
Karma: 1
Posts: 313
|
 |
« Reply #27 on: May 25, 2012, 04:16:40 pm » |
You should make them unsigned, not signed. millis() and micros() will never return a negative value. Look at the reference of a function to see it's return type. 9 times out of 10, that's the data type you want to store the value into.
millis() and micros() return an unsigned long, so you should store the value in an unsigned long. Otherwise you will eventually run into problems.
Got it, I think! So, can I do the following; use a short for the interval, as the interval is constant at 500? unsigned long previousMillis = 0; const unsigned short interval = 500; // creates 500ms interval in which to update serial So as for defining pins as ints, can I not define pins as chars, as they are between 0 and 255 - to save space? For example; const short tempPin = 1; // defines the LM35 input into analogue pin 1 short valFan = 0; // creates an integer used for temperature mapping, this being mapped fan speed - default to 0 const short fanPin = 9; // defines the fan output connected to digital pin 5 Or is this not seen as best practice, if not - why? EDIT: Changed my entire code to the following, and tested - works exactly the same, but the program size is exactly the same replacing the ints with shorts. I thought a short was 1 byte, and int was 2 bytes? /* Uses an LM35 to sense temperature, and drive a cooling fan accordingly. by Julian West http://uk.linkedin.com/pub/julian-west/26/a42/a02 */
const short tempPin = 1; // defines the LM35 input into analogue pin 1 short valFan = 0; // creates an integer used for temperature mapping, this being mapped fan speed - default to 0 const short fanPin = 9; // defines the fan output connected to digital pin 5 const short onboardLED = 13; // defines onboard LED as pin 13 unsigned long previousMillis = 0; const unsigned short interval = 500; // creates 500ms interval in which to update serial
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(); // count milliseconds and assign to currentMillis if(currentMillis - previousMillis > interval) // decides if current millis is greater than interval { previousMillis = currentMillis; short 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(""); } }
|
|
|
|
« Last Edit: May 25, 2012, 04:20:06 pm by jtw11 »
|
Logged
|
|
|
|
|
Global Moderator
UK
Online
Brattain Member
Karma: 137
Posts: 19060
I don't think you connected the grounds, Dave.
|
 |
« Reply #28 on: May 25, 2012, 04:21:18 pm » |
So as for defining pins as ints, can I not define pins as chars No, the type accepted by pinMode, digitalWrite etc for pin numbers is unsigned.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
UK
Offline
Edison Member
Karma: 44
Posts: 2212
What a host of balls she had seen: gaity, the brass buttons...
|
 |
« Reply #29 on: May 25, 2012, 04:26:42 pm » |
I thought a short was 1 byte, and int was 2 bytes? No, a short is 2 bytes. It's specifically 2 bytes on all systems regardless of word size. On a 32-bit system an int is 4 bytes, but a short is still 2 bytes. On an 8-bit system like the AVR an int is 2 bytes emulated as 2 individual bytes with extra code to operate on both as a single digit. A short, not surprisingly, is 2 bytes - exactly the same as an int. As for negative numbers, you need to understand "two's complement", which is how processors and microcontrollers represent negative numbers. Wikipedia has a page on it here: http://en.wikipedia.org/wiki/Two%27s_complement
|
|
|
|
|
Logged
|
|
|
|
|
|