Offline
Newbie
Karma: 0
Posts: 8
|
 |
« on: September 11, 2012, 10:05:27 am » |
Hey all, so I'm writing some little improvements to the Morse example library, but for some reason all of the elements in my byte array are 0 when I run it.. I've tried a couple different things, but it's always the same. I feel like I'm missing something... Code to follow. #include "Arduino.h" #include "Morse.h"
byte dotMatrix[36][5] = { // 0 = ., 1 = -, 2 = no display { 1, 1, 1, 1, 1 }, // 0 ----- { 0, 1, 1, 1, 1 }, // 1 .---- { 0, 0, 1, 1, 1 }, // 2 ..--- { 0, 0, 0, 1, 1 }, // 3 ...-- { 0, 0, 0, 0, 1 }, // 4 ....- { 0, 0, 0, 0, 0 }, // 5 ..... { 1, 0, 0, 0, 0 }, // 6 -.... { 1, 1, 0, 0, 0 }, // 7 --... { 1, 1, 1, 0, 0 }, // 8 ---.. { 1, 1, 1, 1, 0 }, // 9 ----.
{ 0, 1, 2, 2, 2 }, // a .- { 1, 0, 0, 0, 2 }, // b -... { 1, 0, 1, 0, 2 }, // c -.-. { 1, 0, 0, 2, 2 }, // d -.. { 0, 2, 2, 2, 2 }, // e . { 0, 0, 1, 0, 2 }, // f ..-. { 1, 1, 0, 2, 2 }, // g --. { 0, 0, 0, 0, 2 }, // h .... { 0, 0, 2, 2, 2 }, // i .. { 0, 1, 1, 1, 2 }, // j .--- { 1, 0, 1, 2, 2 }, // k -.- { 0, 1, 0, 0, 2 }, // l .-.. { 1, 1, 2, 2, 2 }, // m -- { 1, 0, 2, 2, 2 }, // n -. { 1, 1, 1, 2, 2 }, // o --- { 0, 1, 1, 0, 2 }, // p .--. { 1, 1, 0, 1, 2 }, // q --.- { 0, 1, 0, 2, 2 }, // r .-. { 0, 0, 0, 2, 2 }, // s ... { 1, 2, 2, 2, 2 }, // t - { 0, 0, 1, 2, 2 }, // u ..- { 0, 0, 0, 1, 2 }, // v ...- { 0, 1, 1, 2, 2 }, // w .-- { 1, 0, 0, 1, 2 }, // x -..- { 1, 0, 1, 1, 2 }, // y -.-- { 1, 1, 0, 0, 2 } // z --.. };
Morse::Morse(int pin, int delayTime) { pinMode(pin, OUTPUT); _pin = pin; _delayTime = delayTime; }
void Morse::dot() { digitalWrite(_pin, HIGH); delayDot(); digitalWrite(_pin, LOW); }
void Morse::dash() { digitalWrite(_pin, HIGH); delayDot(); delayDot(); delayDot(); digitalWrite(_pin, LOW); }
void Morse::delayDot() { delay(_delayTime); }
void Morse::delayLetter() { delay(3 * _delayTime); }
void Morse::delayWord() { delay(7 * _delayTime); }
void Morse::writeLetter(int letter) { Serial.print("Output '"+String(letter)+"': ");
for (int i = 0; i < 5; i++) { byte dotmatrixelement = dotMatrix[letter][i]; Serial.print(dotmatrixelement);
if (dotMatrix[letter][i] == 1) dash(); else if (dotMatrix[letter][i] == 0) dot();
if (i < 4) delayDot(); } Serial.println(" ...Done!"); }
void Morse::writeStr(String text) { for (int i = 0; i < 36; i++) { for (int j = 0; j < 5; ++j) { Serial.print(String(dotMatrix[i][j])); } Serial.println(","); }
text.toLowerCase(); for (unsigned int i = 0; i < text.length(); i++) { byte letter = byte(text.charAt(i));
if (letter == 32) { delayWord(); Serial.println("Delay Word..."); } else { if (i != 0) { delayLetter(); Serial.println("Delay letter..."); }
if (letter >= 48 && letter <= 57) { writeLetter(letter - 48); Serial.println("Display '" + text.substring(i, i+1) + "' as " + String(letter)); } else if (letter >= 97 && letter <= 122) { writeLetter(letter - 87); Serial.println("Display '" + text.substring(i, i+1) + "' as " + String(letter)); } } } } My output is ending up like this: Output '18': 00000 ...Done! Display 'i' as 105 Delay Word... Delay letter... Output '21': 00000 ...Done! Display 'l' as 108 Delay letter...
|
|
|
|
« Last Edit: September 11, 2012, 10:08:52 am by Sidneys1 »
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 2
Posts: 212
|
 |
« Reply #1 on: September 11, 2012, 10:35:31 am » |
why do you need a multiple dimensioned array to create morse code ??? be aware that such arrays use a lot of memory.  you only need to store short long and empty so 01 11 00 is enough. If you want to improve you better create something that also does improve for example by using less memmor the letters are made of 4 signals, so in essence you could do this with just 1 byte per letter character. ( A = 01 11 00 00) equals 112 such alfabet stored in bytes would only require 24 bytes, thats a lot less memory. Only numbers require 5 signals so you cannt store them in a single byte (5*2 bits =10 bits). However numbers have a simple presentation invent a function to write and read them.. also not that complex.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Online
Brattain Member
Karma: 311
Posts: 35471
Seattle, WA USA
|
 |
« Reply #2 on: September 11, 2012, 10:37:27 am » |
Serial.print("Output '"+String(letter)+"': "); There is no reason to waste the resources you are wasting to convert letter to a String. Nor are most of the other uses of String necessary. Learn to use char arrays. byte letter = byte(text.charAt(i)); Why is letter a byte? The String::charAt() method returns a char. writeLetter(letter - 87); Why is writeLetter() defined to take an int argument, when all you ever pass it is byte values? What, exactly, are you passing to Morse::writeStr()? The mix of letters, substrings, and Strings in your output is very confusing.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #3 on: September 11, 2012, 05:15:09 pm » |
What, exactly, are you passing to Morse::writeStr()? The mix of letters, substrings, and Strings in your output is very confusing.
Sorry, I'm passing in sentence strings, ex "I love Arduino", which is then put in lower case and each individual char is sent to writeLetter() with the exception of spaces (word pause).
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #4 on: September 11, 2012, 06:06:29 pm » |
Ok, I've updated my code, but it's still returning all zeros... #include "Arduino.h" #include "Morse.h"
byte dotMatrix[36] = { // 01 = ., 10 = -, and 00 = nothing B01100000, // a .- B10010101, // b -... B10011001, // c -.-. B10010100, // d -.. B01000000, // e . B01011001, // f ..-. B10100100, // g --. B01010101, // h .... B01010000, // i .. B01101010, // j .--- B10011000, // k -.- B01100101, // l .-.. B10100000, // m -- B10010000, // n -. B10101000, // o --- B01101001, // p .--. B10100110, // q --.- B01100100, // r .-. B01010100, // s ... B10000000, // t - B01011000, // u ..- B01010110, // v ...- B01101000, // w .-- B10010110, // x -..- B10011010, // y -.-- B10100101 // z --.. };
Morse::Morse(int pin, int delayTime) { pinMode(pin, OUTPUT); _pin = pin; _delayTime = delayTime; }
void Morse::dot() { digitalWrite(_pin, HIGH); delayDot(); digitalWrite(_pin, LOW); }
void Morse::dash() { digitalWrite(_pin, HIGH); delayDot(); delayDot(); delayDot(); digitalWrite(_pin, LOW); }
void Morse::delayDot() { delay(_delayTime); }
void Morse::delayLetter() { delay(3 * _delayTime); }
void Morse::delayWord() { delay(7 * _delayTime); }
void Morse::writeLetter(char letter) { byte MyLetter = dotMatrix[letter]; Serial.println(MyLetter);
for (int i = 0; i < 4; i++) { if ((MyLetter & B11) == 2) dash(); else if ((MyLetter & B11) == 1) dot();
MyLetter = MyLetter >> 2;
if (i < 4) delayDot(); } }
void Morse::writeStr(String text) { text.toLowerCase(); for (unsigned int i = 0; i < text.length(); i++) { char letter = text.charAt(i);
if (letter == 32) { delayWord(); } else { if (i != 0) { delayLetter(); }
if (letter >= 48 && letter <= 57) { //writeLetter(letter - 48); //A number... Do nothing for now. } else if (letter >= 97 && letter <= 122) { writeLetter(letter - 86); } } } }
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6335
-
|
 |
« Reply #5 on: September 11, 2012, 06:21:21 pm » |
When you do the lookup you're using the character's ASCII character code as an index into dotMatrix[], but it's actually initialised with the code for 'a' at index 0. Hence, you need to subtract 'a' from your 'letter' ASCII value to derive the array index. I recommend you put that logic in a lookup function which enforces any assumptions you may be making about capitalisation, applies the 'a' offset and does a sanity check on the resulting array index before returning the array entry.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #6 on: September 11, 2012, 06:37:24 pm » |
If you read the code in Morse::writeStr(String text) you'll see that I already do this. //inside writeStr, line 109 else if (letter >= 97 && letter <= 122) //Check that it's a lowercase letter... { Serial.println(letter); //verified letter = letter - 97; //Offset so a=0 Serial.println(byte(letter)); //verified writeLetter(letter); // still reads a 0 from dotMatrix[] }
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6335
-
|
 |
« Reply #7 on: September 11, 2012, 07:43:40 pm » |
I had missed that, but actually what I see is: writeLetter(letter - 86);
The offset 86 appears wrong. I'd much rather you used character literals rather than decimals so we could follow what you're doing here. Have you printed out the array index and the value read back from the array at that index?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #8 on: September 11, 2012, 08:44:07 pm » |
The offset 86 appears wrong.
Yes, I fixed that (see my last post). I'd much rather you used character literals rather than decimals so we could follow what you're doing here. Ok: //Loop through every letter. for (int i = 0; i < text.length(); i++) { char letter = text[i]; // Access the current letter
if (letter == ' ') delayWord(); // Space between words else { // Check if this isn't the first letter... if (i != 0) delayLetter(); // And if not, pause between letters
// Check to see if this letter falls within the range a-z if (letter >= 'a' && letter <= 'z') { Serial.println(letter); // Verify what letter we're trying to display letter -= 'a'; // Offset it to 'a' Serial.println(byte(letter)); //I want the numeric representation... writeLetter(letter); // Try to display it. } } } Have you printed out the array index and the value read back from the array at that index?
I do have it print all of that information for every character: // From the Serial Monitor i //is the char we're trying to print 8 // is the index of the byte-value for i (zero-based) 0 // is the value that is being retrieving from dotMatrix[]... incorrect!
That is not the issue here, trust me. The issue is my array has all zeros at runtime. I made for loop printing all the values in dotMatrix[], and they are all 0. Why? My C++ array initialization code is (as far as I know) correct, and compiles without error.
|
|
|
|
« Last Edit: September 11, 2012, 09:00:28 pm by Sidneys1 »
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6335
-
|
 |
« Reply #9 on: September 11, 2012, 09:05:06 pm » |
That is not the issue here, trust me. The issue is my array has all zeros at runtime. I made for loop printing all the values in dotMatrix[], and they are all 0. Why? My C++ array initialization code is (as far as I know) correct, and compiles without error.
Can you produce a sketch that does nothing but declare that array and then read and display the content, which demonstrates the problem?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #10 on: September 11, 2012, 10:32:14 pm » |
Can you produce a sketch that does nothing but declare that array and then read and display the content, which demonstrates the problem?
Sure. byte arr[] = { // 01 = ., 10 = -, and 00 = nothing B01100000, // a .- B10010101, // b -... B10011001, // c -.-. B10010100, // d -.. B01000000, // e . B01011001, // f ..-. B10100100, // g --. B01010101, // h .... B01010000, // i .. B01101010, // j .--- B10011000, // k -.- B01100101, // l .-.. B10100000, // m -- B10010000, // n -. B10101000, // o --- B01101001, // p .--. B10100110, // q --.- B01100100, // r .-. B01010100, // s ... B10000000, // t - B01011000, // u ..- B01010110, // v ...- B01101000, // w .-- B10010110, // x -..- B10011010, // y -.-- B10100101 // z --.. };
byte mask[] = { 0x03, 0x0C, 0x30, 0xC0 };
void setup() { // put your setup code here, to run once: Serial.begin(9600); delay(1000); }
void loop() { // put your main code here, to run repeatedly: for (int i = 0; i < 26; i++) { Serial.print(i); Serial.print("\t=\t"); Serial.print(arr[i]); Serial.print("\t=\t");
for (int j = 3; j >=0; j--) { byte masked = arr[i] & mask[j];
masked >>= 2*j;
if (masked == 1) Serial.print('.'); else if (masked == 2) Serial.print('-'); else if (masked == 0) break; } Serial.println(); } delay(2000); } (I also implemented that bitmasking section in the Library, to no avail) Output: 0 = 96 = .- 1 = 149 = -... 2 = 153 = -.-. 3 = 148 = -.. 4 = 64 = . 5 = 89 = ..-. 6 = 164 = --. 7 = 85 = .... 8 = 80 = .. 9 = 106 = .--- 10 = 152 = -.- 11 = 101 = .-.. 12 = 160 = -- 13 = 144 = -. 14 = 168 = --- 15 = 105 = .--. 16 = 166 = --.- 17 = 100 = .-. 18 = 84 = ... 19 = 128 = - 20 = 88 = ..- 21 = 86 = ...- 22 = 104 = .-- 23 = 150 = -..- 24 = 154 = -.-- 25 = 165 = --..
|
|
|
|
« Last Edit: September 11, 2012, 10:34:42 pm by Sidneys1 »
|
Logged
|
|
|
|
|
Des Moines, WA - USA
Offline
God Member
Karma: 21
Posts: 703
|
 |
« Reply #11 on: September 11, 2012, 11:04:05 pm » |
/* ======================================================================================= * File - morse_encoded.pde * --------------------------------------------------------------------------------------- * 03/13/2012 created * 03/14/2012 encoded morse strings as array of 2 bit encoding in 16 bi[quote][/quote]t container * 03/14/2012 encoded 2 bit encoding in 16 bit container using binary constants */ #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif
#include <ctype.h>
#if defined(_BOARD_CEREBOT_MX4CK_) const uint8_t pinLED = 64; // ON-BOARD LED1 #elif defined(_BOARD_UNO_) const uint8_t pinLED = 13; // ON-BOARD LED1 #else #error "!!!Target is unknown board!!!" #endif
const unsigned long DELAY_CASE = 150UL;
const unsigned long DELAY_DOT = DELAY_CASE; // MILLISECONDS const unsigned long DELAY_DOT = DELAY_INTRA; const unsigned long DELAY_DASH = 3 * DELAY_CASE; const unsigned long DELAY_CHAR = 3 * DELAY_CASE; const unsigned long DELAY_WORD = 7 * DELAY_CASE; const unsigned long DELAY_MESSAGE = 3 * 1000; // 3 SECONDS
const uint8_t LED_OFF = LOW; // SYNONYMN FOR READABILITY const uint8_t LED_ON = HIGH; // SYNONYMN FOR READABILITY
#define SIZEOF_ARRAY(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
enum { EOS, DOT, DASH, MASK = 3 };
struct sequence_pair_t { const char character; // character const uint16_t encoding; // sequence, zero terminated 'C' string };
const sequence_pair_t morse_lookup[] = { // STRING OF 2-BIT VALUES ENCODE THE MORSE SEQUENCE, LSB -> MSB // // 00 END-OF-SEQUENCE // 01 '.' // 10 '-' // 11 UNUSED
// EXAMPLES: // // { 'A', 0b0000000000001101 } // ".-" EOS EOS EOS EOS EOS EOS DASH DOT //, { '0', 0b0000001010101010 } // "-----" EOS EOS EOS DASH DASH DASH DASH DASH
// --- Numeric { '0', 0b0000001010101010 } // "-----" , { '1', 0b0000001010101001 } // ".----" , { '2', 0b0000001010100101 } // "..---" , { '3', 0b0000001010010101 } // "...--" , { '4', 0b0000001001010101 } // "....-" , { '5', 0b0000000101010101 } // "....." , { '6', 0b0000000101010110 } // "-...." , { '7', 0b0000000101011010 } // "--..." , { '8', 0b0000000101101010 } // "---.." , { '9', 0b0000000110101010 } // "----." // --- Alphabetic , { 'A', 0b0000000000001001 } // ".-" , { 'B', 0b0000000001010110 } // "-..." , { 'C', 0b0000000001100110 } // "-.-." , { 'D', 0b0000000000010110 } // "-.." , { 'E', 0b0000000000000001 } // "." , { 'F', 0b0000000001100101 } // "..-." , { 'G', 0b0000000000011010 } // "--." , { 'H', 0b0000000001010101 } // "...." , { 'I', 0b0000000000000101 } // ".." , { 'J', 0b0000000010101001 } // ".---" , { 'K', 0b0000000000100110 } // "-.-" , { 'L', 0b0000000001011001 } // ".-.." , { 'M', 0b0000000000001010 } // "--" , { 'N', 0b0000000000000110 } // "-." , { 'O', 0b0000000000101010 } // "---" , { 'P', 0b0000000001101001 } // ".--." , { 'Q', 0b0000000010011010 } // "--.-" , { 'R', 0b0000000000011001 } // ".-." , { 'S', 0b0000000000010101 } // "..." , { 'T', 0b0000000000000010 } // "-" , { 'U', 0b0000000000100101 } // "..-" , { 'V', 0b0000000010010101 } // "...-" , { 'W', 0b0000000000101001 } // ".--" , { 'X', 0b0000000010010110 } // "-..-" , { 'W', 0b0000000010100110 } // "-.--" , { 'Z', 0b0000000001011010 } // "--.." // --- Punctuation , { ',', 0b0000101001011010 } // "--..--" , { '.', 0b0000100110011001 } // ".-.-.-" , { ':', 0b0000010101101010 } // "---..." , { '?', 0b0000010110100101 } // "..--.." , { '-', 0b0000100101010110 } // "-....-" , { '/', 0b0000000110010110 } // "-..-." , { '(', 0b0000100110100110 } // "-.--.-" , { ')', 0b0000100110100110 } // "-.--.-" // , { '\'', ".----." } // the windows IDE has problem with escaped character literals! // , { '\"', ".-..-." } // the windows IDE has problem with escaped character literals! };
void blinkDot() { digitalWrite(pinLED, LED_ON);
delay(DELAY_DOT);
digitalWrite(pinLED, LED_OFF); }
void blinkDash() { digitalWrite(pinLED, LED_ON);
delay(DELAY_DASH);
digitalWrite(pinLED, LED_OFF); }
void blinkCharacterSequence(uint16_t encoding) { do { switch ( encoding & MASK ) { case DOT: blinkDot(); break; case DASH: blinkDash(); break; }
if ( encoding >>= 2 ) { delay(DELAY_INTRA); }
} while ( EOS != (encoding & MASK) ); }
void blinkCharacter(char ch) { const int cEntries = SIZEOF_ARRAY(morse_lookup); for ( int i = cEntries; i--; ) { if ( ch == morse_lookup[i].character ) { blinkCharacterSequence(morse_lookup[i].encoding);
return; } } }
void loop() { // Initialize message using "string" syntax which has invisible // terminating 0
static const char szMessage[] = { "FORMERLY WB7AKS (1979)!" };
for ( int i = 0; szMessage[i]; ) { blinkCharacter(toupper(szMessage[i++])); delay(((' ' != szMessage[i]) ? DELAY_CHAR : DELAY_WORD)); } delay(DELAY_MESSAGE); }
void setup() { pinMode(pinLED, OUTPUT); digitalWrite(pinLED, LED_OFF); delay(DELAY_MESSAGE); }
|
|
|
|
« Last Edit: September 11, 2012, 11:27:44 pm by lloyddean »
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6335
-
|
 |
« Reply #12 on: September 12, 2012, 02:07:31 pm » |
That is not the issue here, trust me. The issue is my array has all zeros at runtime. I made for loop printing all the values in dotMatrix[], and they are all 0. Why?
The output you quoted does not seem to show the problem you describe of the array containing zeroes. What is the actual problem here?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #13 on: September 12, 2012, 02:42:55 pm » |
The output you quoted does not seem to show the problem you describe of the array containing zeroes. What is the actual problem here?
Correct. To test this further I rewrote the Library from scratch - same problem exists: it is reading zeros from the array. But, oddly, after a couple of iterations it starts reading completely random data from the array (probably memory corruption) - but there's the catch: I copied the exact same code out of the Library and into a raw sketch and it runs without a problem, no questions asked. Perfect functionality. No clue what's going on here, other than maybe there is something wrong with the way the compiler handles libraries. ~Sidneys1
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 2
Posts: 212
|
 |
« Reply #14 on: September 12, 2012, 04:35:52 pm » |
hm, this might have to do something with the scope of the code, i wonder. Usually libraries contain functions, and do things separately from main code It might be that the values are private only available in your library itself. this might interest you http://stackoverflow.com/questions/5620256/understanding-how-to-correctly-treat-c-class-constantsthere are other methods too [url]http://codewrangler.home.comcast.net/~codewrangler/tech_info/cpp_const.html[/ur] depending on the code one could keep values inside the library (and have functions exposed of how to respond*.) or expose variables like the alphabet to outside the library. *Like Send(pin,"SOS") and msg=Read(pin)
|
|
|
|
|
Logged
|
|
|
|
|
|