Can I loop a float char by char or do I have to convert the float?

Hello,
My first post and question in this forum. :wink:

My current project is to make a weather station that reads values from different sensors, and sends the data wireless to the my house. Most of the data will contain decimals so I guess float is the best data type to use when receiving the data from the sensors.

For now I have a sensor (DHT11) that i can read humidity and temperature with. I leave the humidity for now and just reading the temperature.

What I want is to take the temperature (for example float t = 24.00 Celsius) as a float and loop trough every character to send each character as morse code to my house. I can print the temperature value as it is to the serial monitor but I can't loop the value character by character. I guess I have to convert the "float t" to a string or something so that the value can be looped.
Am I right or can I loop through the temperature value as it is some how?
In case I have to convert the float in to a string or char, what is the best way to do that?

Changing the loop and putting the temperature instead of the hardcoded string stringToMorseCode ("whatever") as below doesn't seem to work.
// Read temperature as Celsius
float t = dht.readTemperature(false);
for (int i = 0; i < sizeof(t) - 1; i++)
{
// Get the character in the current position
char tmpChar = t*;*
// Print the character to serial monitor
Serial.print(tmpChar);
// Send the character as morse code
GetChar(tmpChar);
}
Entire code:
```
/
 Morse Code Project
 
 This code will loop through a string of characters and convert these to morse code.  
 It will blink two LED lights and play audio on a speaker.  
*/

#include<stdlib.h>
#include <DHT.h>
#define DHTPIN 7     // the sensors pinnumber

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11

// Initialize DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);

// Create variable to define the output pins
int led = 9;        // light up a led on transmission
int audio = 8;      // output audio
int note = 1200;      // music note/pitch

/*
Set the speed of your morse code
Adjust the 'dotlen' length to speed up or slow down your morse code
(all of the other lengths are based on the dotlen)

Here are the ratios code elements:
  Dash length = Dot length x 3
  Pause between elements = Dot length
	  (pause between dots and dashes within the character)
  Pause between characters = Dot length x 3
  Pause between words = Dot length x 7

http://www.nu-ware.com/NuCode%20Help/index.html?m...
*/
int dotLen = 40;     // length of the morse code 'dot'
int dashLen = dotLen * 3;    // length of the morse code 'dash'
int elemPause = dotLen;  // length of the pause between elements of a character
int Spaces = dotLen * 3;     // length of the spaces between characters
int wordPause = dotLen * 7;  // length of the pause between words

void setup() {

Serial.begin(9600);

// Start reading the sensor
 dht.begin();
}

void loop()
{
 // Read temperature as Celsius
 float t = dht.readTemperature(false);
 
   char stringToMorseCode[] = "whatever ";
 
  // Loop through the string and get each character one at a time until the end is reached
 for (int i = 0; i < sizeof(stringToMorseCode) - 1; i++)
 {
   // Get the character in the current position
char tmpChar = stringToMorseCode[i];
       
       // Print the character to serial monitor
       Serial.print(tmpChar);
       
// Send the character as morse code
GetChar(tmpChar);
 }

// Print out the temperature
 Serial.print(t);

// Break line
 Serial.println();
 
 // Wait a while between measurements.
 
 // using this delay while testing
 delay(2000);

// Aprox every five minutes
 //delay(299750);

}

// DOT
void MorseDot()
{
 tone(audio, note, dotLen); // start playing a tone
 delay(dotLen);             // hold in this position
}

// DASH
void MorseDash()
{
 tone(audio, note, dashLen); // start playing a tone
 delay(dashLen);               // hold in this position
}

// Turn Off
void LightsOff(int delayTime)
{
 noTone(audio);         // stop playing a tone
 delay(delayTime);             // hold in this position
}

// *** Characters to Morse Code Conversion *** //
void GetChar(char tmpChar)
{
// Take the passed character and use a switch case to find the morse code for that character
switch (tmpChar) {
 case '1':
   MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
break;
 case '2':
   MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
break;
 case '3':
   MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
break;
 case '4':
   MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
break;
 case '5':
   MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
break;
 case '6':
   MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
break;
 case '7':
   MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
break;
 case '8':
   MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
break;
 case '9':
   MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDot();
LightsOff(elemPause);
break;
 case '0':
   MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
MorseDash();
LightsOff(elemPause);
break;
 default:
// If a matching character was not found it will default to a blank space
LightsOff(Spaces);
}
}
_
```*_

Hello and welcome,

Use function dtostrf to convert a float into a string

float Value = 1.2345;
char StringValue[11] = ""; // for a 10 character string
dtostrf(Value, 10, 2, StringValue); // for a 10 character string with 4 decimal places

dtostrf converts doubles to strings. It works for floats as well. Don't have my Arduino on me so can't test with that specifically, but tested it in my C compiler for PC's and it works.

There are something just short of a bazillion ways to encode/decode Morse code. (See: Arduino Projects for Amateur Radio at Amazon.com.) However, one that you might find useful is suggested here:

char morseTable[][6] = {
    "01",              // A = dit dah
    "1000",            // B = dah dit dit dit  etc.
    "1010",            // C
    "100",             // D
    "0",               // E
    "0010",            // F
    "110",             // G
    "0000",            // H
    "00",              // I
    "0111",            // J
    "101",             // K
    "0100",            // L
    "11",              // M
    "10",              // N
    "111",             // O
    "0110",            // P
    "1101",            // Q
    "010",             // R
    "000",             // S
    "1",               // T
    "001",             // U
    "0001",            // V
    "011",             // W
    "1001",            // X
    "1011",            // Y
    "1100"             // Z
} ;

This would simplify your switch/case code quite a bit. I think you could work out the number codes very simply.

Jack, W8TEE

AHA! Now I see! ;D
I tried that dtostrf() function but I did not understand the syntax. My guess was that the function returns a value so i've tried this yesterday;
char tLength[7]
String newTemp = dtostrf(t, 6, 2, tLength);

So if I understand this right, in the below loop example.
The temperature can be "24.00" or "-12.00" (5-6 characters).

char tString[7] has to be at least one more in length than the actual string for some reason, and are the new variable containing the converted value.
And the other arguments (6,2) are setting the length of the total length and the decimals of the ingoing value in the variable "t".

This made it work and I will try to learn why the last argument has to be an array one more longer than the actual length.
Thank you soo much for your pointers! :slight_smile:

Thank you econjack for the completion of the morse code. I cut that out because my post got to long. ??? But I like that solution better, its much more neat and I may adopt that.

My new loop:

void loop()
{ 
  // Read temperature as Celsius
  float t = dht.readTemperature(false);
  
  // Set the stringsize
  char tString[7] = ""; // for a 6 character string
  
  // Convert the float t to String tString
  dtostrf(t, 6, 2, tString); // for a 6 character string with 2 decimal places

  // Loop through the tString character by character
  for (int i = 0; i < sizeof(tString) - 1; i++)
  {
    // Get the character in the current position
	char tmpChar = tString[i];
        
        // Print the character to serial monitor
        Serial.print(tmpChar);
        
	// Send the character as morse code
	GetChar(tmpChar);
  }
  // Break line
  Serial.println();
  
  // Wait a while between measurements.
  
  // using this delay while testing
  delay(5000);

  // Aprox every five minutes
  //delay(299750);

}

This made it work and I will try to learn why the last argument has to be an array one more longer than the actual length.

The reason is because strings that are built up from char arrays need to have a null termination character ('\0') at the end of the string. The compiler uses that character as a sentinel to tell it where the string ends. So, if you see the string:

   char msg[] = "Hello world.";

The contents of msg[] in memory looks like:

'H', 'e', 'l','l,'o', ' ', 'w','o','r','l','d','\0'

That last character is called the null character. The backslash is needed so the compiler knows it is not the digit character '0' (i.e., zero).

Schnebban:
Hello,
My first post and question in this forum. :wink:

My current project is to make a weather station that reads values from different sensors, and sends the data wireless to the my house. Most of the data will contain decimals so I guess float is the best data type to use when receiving the data from the sensors.

Float data is not stored as a string. It's stored as 4 bytes of IEEE floating point data. Looping through each byte of a floating point value will give you gibberish.

Also, your method was wrong... it's not (0; sizeof()-1, ++), it's just sizeof. The size of a float is 4 bytes, so you would loop from 0 to "less than 4" which is 3 (i.e. 0 to 3) which is what you would have wanted.

Anyway, what you need to do is convert your floating point value to an ascii string, then send it out. Use the dtostrf() function. And don't use the String library, just create a small buffer for the value, like this:

[b]char buffer [16];
dtostrf (value, 6, 2, buffer);

[/b]

now "buffer" contains the ascii string value of the floating point variable "value".

As far as morse code goes, why do it in such a difficult manner?

All you need is something like this:

const char *morse[] = {
    ".-",
    "-...",
    "-.-.",
    ".",
// ... etc...
};

uint8_t x;
uint8_t c = toupper (in) - 'A';
for (x = 0; x < strlen(morse[c]); x++) {
    if (morse[c][x] == '-') {
        beep (3X);
    } else {
        beep (1X);
    }
}
silence (2X);

That's pseudo code of course. The "beep 3X" means make a tone of 3 "durations" in length, the dot makes a tone of 1 "duration" then there is a 2 "duration" silence between letters.
You take your incoming character, convert it to uppercase, then subtract ascii "A" from is to make it an index (A==0, B==1, etc..) then index into the morse list and scan out each character "-" or "." in the selected string element.

Make sense?