You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于nesC中AMSend.send与Receive.receive冲突及单跳通信可靠性的问询

I’ve dealt with exactly this kind of reliability issue in nesC/TinyOS projects before, so let’s walk through what’s going on here and how to fix it.


First: Are AMSend.send and Receive.receive conflicting?

Absolutely not. AMSend.send() returning SUCCESS only means your packet was accepted by the MAC layer for transmission—it doesn’t guarantee the packet was actually sent, received, or acknowledged. The Receive.receive event fires independently on the receiving node when a valid packet is decoded, so these two operations don’t block or preempt each other.

Why you’re seeing missing Receive.receive events

Looking at your code and setup, there are a few key issues causing the reliability gap:

  1. Broken locked variable logic
    In your sendDone event, you only set locked = FALSE if the packet was acknowledged. If the ACK fails (e.g., due to wireless interference), locked stays TRUE forever, blocking all future sends. That means after one failed ACK, your node stops sending entirely—so the other node has nothing to receive.

  2. No retransmission for failed packets
    Even with PacketAcknowledgements, wireless packets (or their ACKs) can get lost. Your current code just logs "NOT ACKED!" and discards the packet, so the receiving node will never get it, and Receive.receive won’t fire.

  3. Potential configuration mismatches

    • Ensure both nodes use the same AM group. If your Makefile doesn’t set AM_GROUP, nodes might be in different groups and ignore each other’s broadcast packets.
    • Double-check the definition of radio_count_msg_t—byte alignment issues (common in TinyOS) could make your len check in Receive.receive fail silently, so you won’t see the debug log for mismatched packets.

Fixes for reliable single-hop communication

Let’s adjust your code and configuration to resolve these issues:

1. Fix the locked variable handling

Always release the lock in sendDone, regardless of ACK success. The packet is no longer in use once sendDone fires, so you need to allow future sends:

event void AMSend.sendDone(message_t* bufPtr, error_t error) {
  if(&packet == bufPtr){
    if (call PacketAcknowledgements.wasAcked(bufPtr)==SUCCESS){
      dbg("RadioCountToLedsC", "packet %u sent and ACKed.\n", counter);
    } else {
      dbg("RadioCountToLedsC", "packet %u NOT ACKED! Retrying...\n", counter);
      // Re-post the send task to retry the failed packet
      post senddatatask();
    }
    locked = FALSE; // Critical: release lock every time
  }
}

2. Add retransmission logic (preserve counter values)

To avoid incrementing the counter on retries, add a global variable to track the current packet being sent:

// Add this global variable to track the active packet's counter
uint16_t current_send_counter = 0;

task void senddatatask() {
  if (locked==TRUE) {
    return;
  } 
  locked = TRUE;
  
  // Only increment counter if we're sending a new packet, not retrying
  if (current_send_counter == 0 || call PacketAcknowledgements.wasAcked(&packet) == SUCCESS) {
    counter++;
    current_send_counter = counter;
  }
  
  radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t));
  if (rcm == NULL) {
    locked = FALSE; // Release lock if payload allocation fails
    return;
  }
  rcm->counter = current_send_counter;
  call PacketAcknowledgements.requestAck(&packet);
  
  if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) != SUCCESS) {
    locked = FALSE; // Release lock if send is rejected
    dbg("RadioCountToLedsC", "Send rejected by MAC layer!\n");
  }
}

3. Ensure consistent AM group configuration

Add this line to your Makefile to make sure both nodes are in the same communication group:

CFLAGS += -DAM_GROUP=0x01

4. Debug receive events more thoroughly

Modify your Receive.receive event to log all incoming packets, even if the length doesn’t match—this will help you rule out alignment or corruption issues:

event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len) {
  dbg("RadioCountToLedsC", "Received packet with length %u (expected %u)\n", len, sizeof(radio_count_msg_t));
  
  if (len != sizeof(radio_count_msg_t)) {
    return bufPtr;
  } 
  
  radio_count_msg_t* rcm = (radio_count_msg_t*)payload;
  dbg("RadioCountToLedsC", "Received counter: %u\n", rcm->counter);
  return bufPtr;
}

Final Notes

  • Even with ACKs and retries, wireless communication isn’t 100% perfect, but these fixes will drastically improve reliability for single-hop links.
  • If you’re still seeing missing packets, check the physical placement of your nodes—too much distance or obstacles can cause signal loss, even in simple two-node setups.

内容的提问来源于stack exchange,提问作者ybk1996

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:49:48