Project

General

Profile

JeeLink outputting code-localized gibberish to Serial Monitor

Added by rweaver almost 7 years ago

I’m building a network in which each remote JeeNode (i) occasionally “chats” with the base JeeNode to see if it should be active or idle; and (ii) when active, frequently transmits data from the PIR sensor connected to it. The number of remotes is small enough (currently 2) and the required chat frequency long enough (once per 5 min when in production) that I simplified this way: when the base receives a chat-initiation packet, it conducts this (brief) chat through its conclusion, during which time it ignores all other remotes.

From the perspective of the base, a “chat” consists of:
# Receiving a packet from a remote whose payload is flagged with an “admin” bit (to distinguish it from sensor data). This both implicitly initiates a chat and reports the remote’s active/idle status and battery level.
# Sending a reply packet with instructions to activate or go idle. Packet contains ACK header bit to request ack.
# Receiving an ack packet (CTL==1 & also flagged “admin”).
(Steps 2 and 3 repeated up to 8x, listening for ack for 200ms/cycle, until ack received.)

All works well, except: The JeeLink Serial.print()s goings-on to the Serial Monitor, and a particular part of the code always outputs gibberish. Relevant parts of the code running on the JeeLink:

void loop () {
  if (rf12_recvDone() && rf12_crc == 0 && rf12_len == sizeof inmsg) {  // inmsg is a global struct
    inhdr = rf12_hdr;  // inhdr is a global byte
    memcpy(&inmsg, (byte*) rf12_data, sizeof inmsg);
    if (inmsg.admin)
      chatWithRemote();
    else
      procSensorData();
  }
}

boolean chatWithRemote() {
    // extract from header byte id; booleans dst, ack, ctl [code omitted for brevity]
    // validate header data [omitted for brevity]

    Serial.print(id);
    Serial.print(":  BeginChat  actv=");
    Serial.print(inmsg.active);
    Serial.print(" lowb=");
    Serial.println(inmsg.lowbat);

    BaseMsg outmsg;
    outmsg.activate = proxyCmd;  // a constant (1) acting as proxy for true command

    // outer loop: repeatedly reply and wait for ack
    byte replies = 0;
    while (replies < MaxReplies) {
        rf12_sendNow(id | RF12_HDR_DST | RF12_HDR_ACK, &outmsg, sizeof outmsg);
        rf12_sendWait(2);
        replies++;

        // inner loop: listen for ack up to specified time
        RemoteMsg ackmsg;
        MilliTimer timer;
        while (!timer.poll(200)) {
            if (rf12_recvDone() && rf12_crc == 0 && rf12_len == sizeof ackmsg) {
                memcpy(&ackmsg, (byte*) rf12_data, sizeof ackmsg);
                byte ackid  = rf12_hdr & RF12_HDR_MASK;
                byte ackctl = rf12_hdr & RF12_HDR_CTL;
                if (ackid==id && ackctl) {
                    // series of Serial.print()s indicating "EndChat" [omitted for brevity]
                    return true;
                }
            }
            else {
                // Serial.print()s indicating error [omitted for brevity]
                return false;
            }
        }
    }
    return false;  // if we made it this far, ack never received
}

The Serial Monitor consistently outputs gibberish for all Serial.print()s after the first Serial.print(id) until the “EndChat” output. Output to the Serial Monitor from procSensorData() [code omitted for brevity] is fine. Here’s an example (while I have two remotes, I’m only using one while debugging this):

[begin tommy doorbell v0.5.4.base]
 ^ i30 g51 @ 915 MHz 
1: €ÿÖVËk
+‹RÔ,—W‚b½Ý‰õÁjRþ1:  EndChat   ctl=1 repl=1
1:  Data      motion=0
1:  Data      motion=0
1:  Data      motion=1
1:  Data      motion=0
1: €ÿÖVËk
+‹RÔ,—WŠb½Ý‰õÁjRþ1:  EndChat   ctl=1 repl=1
1:  Data      motion=1
1:  Data      motion=1

Info about my setup and some attempts I’ve made to solve my problem:
* My JeeNodes are v6; my JeeLink is v3.
* I’m running Arduino IDE 1.0.3 on a Mac with OS X 10.8.3.
* setup() contains Serial.begin(57600); Serial Monitor window baud rate is also 57600.
* RF12demo verifies that basic communications between JeeLink and the remotes are all fine. All use the same netgroup and frequency band, and have distinct IDs.
* I’ve tried many combinations of Serial.flush() and delay(ms) in lots of places in the code. Though maybe not the correct combination?
* A post in the old JeeLabs forums explains that there’s interference between Sleepy and Serial Monitor output. While this shouldn’t affect me — my base JeeLink doesn’t use Sleepy — I still tried omitting use of Sleepy by the remote nodes. Unsuccessful.
* I speculated that MilliTimer might interfere with Serial Monitor output, so tried omitting MilliTimer in lieu of a home-grown timer I coded. Unsuccessful.

Sorry this post is so long — just want to provide all relevant info. Thanks in advance for any help.


Replies (12)

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by JohnO almost 7 years ago

That is an odd one. Do you have any interrupt code in there? I wonder what would happen if you had a Serial.print(“ABCDEF”); after your Serial.print(id);

Also, what does your declaration for id look like?

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by rweaver almost 7 years ago

Thanks for your help!

The JeeLink code contains no interrupt code.

Here are my declarations related to id:

byte    inhdr;  // this is a global variable
byte    id = inhdr & RF12_HDR_MASK;  // this is declared inside chatWithRemote()

I added Serial.print(“ABCDEF”) after Serial.print(id) as you suggested. As you can see, Serial Monitor outputs “AB” but then devolves as before:

[begin tommy doorbell v0.5.4.base]
 ^ i30 g51 @ 915 MHz 
1ABÿ€€遂•¥¹
¡…сŠÑÙõÁ‚b½Ý‰õÁjRþ1:  EndChat   ctl=1 repl=1
1:  Data      motion=1
1:  Data      motion=0
1:  Data      motion=1
1:  Data      motion=0
1:  Data      motion=0
1ABÿ€€遂•¥¹
¡…сŠÑÙõłb½Ý‰õÁjRþ1:  EndChat   ctl=1 repl=1
1:  Data      motion=1
1:  Data      motion=0

One other thing: at some point during debugging, I inserted Serial.print(“HI!”); (or maybe Serial.println(.), I can’t remember) at the top of chatWithRemote(). The result was that “HI!” was output, remote node id was NOT output, and subsequent output was fine. In other words, with the exception of (repeatedly) dropping id, Serial Monitor output exactly what I expected. But I can no longer reproduce this result. (And while it was a lot better than what I have now, it still wasn’t quite right.)

Finally, in case it’s helpful I’ve attached a Zip archive of the code running on both the base JeeLink and remote JeeNodes.

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by JohnO almost 7 years ago

How does Serial.print(id, DEC); perform?

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by JohnO almost 7 years ago

Probably the same, I am wondering what value is being passed to your terminal emulator. Perhaps it is a command to reset or
enter a special terminal mode.

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by rweaver almost 7 years ago

Yes, I checked and Serial.print(id, DEC); doesn’t change anything.
Re: your follow-up message about the value being passed to my terminal emulator: I apologize, but can you please elaborate? I understand what you’re saying conceptually, but I don’t know what value I’m passing to the terminal other than the byte variable id, which should and apparently does contain the value 1.
I really appreciate your help and will try any suggestions you offer. I just don’t understand this one.

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by JohnO almost 7 years ago

Ah, you are printing values from a structure. Try assigning the structure values to local variables and then just print the local variable. I realise now that id appears to have a value “1” and is printing correctly.

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by JohnO almost 7 years ago

You can tell my C is not strong. Sleep calls me now.

Good luck!

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by rweaver almost 7 years ago

Yes, id==1 and prints correctly — sorry I didn’t clarify that.
I tried assigning the struct values to local variables; no luck.
Then I tried something more basic: Removing all variables from Serial.print(.) statements, instead outputting only strings. So after the one-time declarative “[begin…]”, my code is now written such that only 4 things, all constant strings, are ever output to the Serial Monitor, all using Serial.println(.):
* At the top of chatWithRemote(): “chat with remote”
* In the send-listen loop, upon receiving ack from remote: “done chatting”
* In the send-listen loop, if no ack received after 8 attempts: “Error: expected ack msg” (note I usually get an ack after just 1 send)
* Inside procSensorData(): “sensor data”

The results are strange and dispiriting: I still get gibberish in the same code location as always:

[begin tommy doorbell v0.5.4.base]
 ^ i30 g51 @ 915 MHz 
cøÿ€€ÿÿÝ¥Ñ¡É•µ½Ñ•5)þdone chatting
sensor data
sensor data
sensor data
sensor data
cøÿ€€ÿÿÝ¥Ñ¡É•µ½Ñ•5)þdone chatting
sensor data
sensor data

Thanks again for all your help. If your dreams supply you with any other suggestions, please let me know….

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by JohnO almost 7 years ago

I wonder if you are running out of RAM. Have you tried a “delay(2000);” between each print statement? Have you tried changing all the Serial.print to Serial.println?

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by JohnO almost 7 years ago

I have used the code below to check on RAM space - I picked it up from some of jcw’s work!

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

SOLVED (mostly): JeeLink outputting code-localized gibberish to Serial Monitor - Added by rweaver almost 7 years ago

I tried @JohnO’s most recent two suggestions, unfortunately without success (I had plenty of available RAM).

But I have eliminated the problem. I decided to start over with a very bare-bones version of the code on both the base and remotes. After verifying that this worked as expected (including no gibberish output to the Serial Monitor), I slowly added back in chunks of functionality, checking at each step to ensure that Serial Monitor output was okay. The good news is that after building back up to the level of functionality I was trying to debug, I now have a working network with no sign of the gibberish output from before. The bad news is that I’m still not sure what caused the problem, and therefore which of my change(s) fixed it. (The rebuilt code is functionally equivalent to what I had before, but there are some changes in specifics, so I can’t directly compare the before and after.)

But here are a few modest insights:
* The payloads I was sending between nodes were originally structs. One such struct (used for payload from the remotes) used bitfields. I thought this might somehow be causing the problem, but replacing these structs with native types didn’t help.
* At one point in my debugging I discovered that I could print to the Serial Monitor without incident just before using memcopy(.) (to copy an incoming packet’s payload to a local variable), but Serial.print(.)ing just after memcopy(.) (including merely printing a constant string unrelated to the memcopied content) was corrupted as gibberish. But replacing memcopy with other methods of reading the payload, such as the “magic incantation” described in http://jeelabs.org/2010/12/08/binary-packet-decoding-%E2%80%93-part-2/, didn’t solve the problem. I’ve tentatively concluded that the error showing up at that particular point was merely a symptom of some underlying problem rather than a problem with memcopy(.) or its variants themselves.
* In the end, my best guess is that the solution was simply slowing things down, using the right combination of delay(s) and {MilliTimer}.poll(.) values. As I said in my initial post, I had already tried a lot of combinations, so I’m not sure why this works now except that I always make sure every rf12_sendXXX(.) is preceded by a delay of at least 100 ms, which for my purposes doesn’t hurt anything at all. I do not, however, use Serial.flush() anywhere in my code.

Anyway, thanks again to @JohnO for your persistent help and many suggestions!

RE: JeeLink outputting code-localized gibberish to Serial Monitor - Added by jcw almost 7 years ago

Sorry to hear about your troubles - it may have been the same issue as described here:

http://jeelabs.net/boards/7/topics/1760?r=1763\#message-1763

    (1-12/12)