Pages: [1] 2   Go Down
Author Topic: Multi-dimensional byte array Init  (Read 1363 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
#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 Offline
Full Member
***
Karma: 2
Posts: 212
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Online
Brattain Member
*****
Karma: 549
Posts: 46100
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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.

Code:
byte letter = byte(text.charAt(i));
Why is letter a byte? The String::charAt() method returns a char.

Code:
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 Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, I've updated my code, but it's still returning all zeros...

Code:
#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 Offline
Shannon Member
****
Karma: 184
Posts: 11173
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you read the code in Morse::writeStr(String text) you'll see that I already do this.

Code:
//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 Offline
Shannon Member
****
Karma: 184
Posts: 11173
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I had missed that, but actually what I see is:
Code:
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

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
//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 Offline
Shannon Member
****
Karma: 184
Posts: 11173
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you produce a sketch that does nothing but declare that array and then read and display the content, which demonstrates the problem?

Sure.

Code:
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:
Code:
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 Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
/* =======================================================================================
 * 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 Offline
Shannon Member
****
Karma: 184
Posts: 11173
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Full Member
***
Karma: 2
Posts: 212
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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-constants
there 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

Pages: [1] 2   Go Up
Jump to: