How to sense channel in Contiki? - contiki

What is the function call or set of instructions required to perform channel sensing in MAC layer of Contiki?
I want to test custom MAC protocols, so for example in CSMA, channel sensing is required before transmission.
I have gone through 'contiki/core/net/mac/csma.c' to see how they have done channel sensing. But I could only see scheduling of queue packets and status checks.
How are they checking if channel is busy before transmission?

You can do this:
if(NETSTACK_RADIO().channel_clear()) {
printf("channel not busy\n");
} else {
printf("channel busy\n");
}
The channel check is implemented in the radio driver. Contiki has platform independent radio API. The actual, platform-specific driver is available through NETSTACK_RADIO API, as demonstrated above. The check is used b the RDC (radio duty cycling) layer, for example, ContikiMAC.

Related

How to disable address filtering in Contiki-NG cc2420 radio module?

When trying to disable address filtering by changing RADIO_PARAM_RX_MODE like below, cc2420 auto ack is not working and motes get duplicated packets.
radio_value_t radio_rx_mode;
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
radio_rx_mode &= ~RADIO_RX_MODE_ADDRESS_FILTER;
if(NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode) != RADIO_RESULT_OK) {
LOG_WARN("radio does not support setting RADIO_PARAM_RX_MODE\n");
}else{
LOG_INFO("turned of Address filtering.\n");
}
How to turn off just address filtering?
Your code is the correct way to disable the address recognition / filtering.
Regarding auto-ACK, the CC2420 datasheet says this:
If MDMCTRL0.AUTOACK is enabled, an acknowledge frame is transmitted for all incoming frames accepted by the address recognition with the acknowledge request flag set and a valid CRC. AUTOACK therefore does not make sense unless also ADR_DECODE and AUTOCRC are enabled.
This means that if you have address filtering disabled, you need to send software ACK.

ESP8266 5v Relay USB Disconnection issue

Issue
-When using the ESP8266 wired up in this way it will randomly disconnect the USB interface when it powers the relay. It may then re-connect but is sporadic.
-The code can be viewed below, but essentially the relay is powered for 300ms then waits 10 seconds to loop.
Wiring Diagram https://i.stack.imgur.com/4mycx.png
Tests:
I have swapped out the relay, pump, ESP8266, aswell as re-wiring the circuit multiple times to check for a short. I also have a integer incrementing every loop cycle, when the ESP8266 is able to re-connect it will print this variable, which shows the board is not crashing:
Serial output
https://i.stack.imgur.com/ziM8g.png
I then modified the diagram so the 5v power was not in parallel, but where two different power sources, one for the ESP8266 and one for the pump circuit, however the same issue was observed:
Test Wiring Diagram https://i.stack.imgur.com/7S0aP.png
Question:
Why does the USB disconnect when sending the control signal to the relay?
Is there a way to mitigate this?
Code:
int relayInput = 5; // the input to the relay pin
int debug_test = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(relayInput, OUTPUT); // initialize pin as OUTPUT
}
void loop() {
// put your main code here, to run repeatedly:
debug_test ++ ;
Serial.println(debug_test);
digitalWrite(relayInput, HIGH); // turn relay on
Serial.println("Water on!");
delay(300);
digitalWrite(relayInput, LOW); // turn relay off
Serial.println("Water off!");
Serial.println("Waiting 10 seconds");
delay(10000);
}
Parts:
Pump - https://www.ebay.co.uk/itm/Mini-Water-Pump-DC-3V-4-5V-Fish-Tank-Fountain-Aquarium-Submersible-White-Parts/174211676084?hash=item288fd337b4:g:128AAOSwfQteYWF3
ESP8255 - https://www.amazon.co.uk/gp/product/B07F5FJSYZ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
Relay - https://www.amazon.co.uk/gp/product/B07BVXT1ZK/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
Ok, so researching in to this, it seems when the pump is on it pulls more current (amps) than the PC can provide.
This will be used connected to a external power source which should supply enough current to it, however I also wanted the flexibility to connect it to a PC with a serial connection to troubleshoot.
So in the end something like this:
https://i.stack.imgur.com/MKD1h.png
You are driving a 5v relay module with 3.3v output, which works perfectly for some people but it depends on the relay module and the board, this might be the problem. or the relay draws more than 12mA which is the maximum current can the ESP8266's GPIO deliver.
so I suggest you use an external power source for the relay and control it through the pin (D1 in your case).
Or just use a generic 5v relay with an external 5v power source and control it using a transistor, here is a circuit.
Additional information: https://electronics.stackexchange.com/questions/213051/how-do-i-use-a-5v-relay-with-a-3-3v-arduino-pro-mini?

TinyOs nesc Packet acknowledge

I want to write a mote-mote radio communication program, and want the receiver acknowledges back to the sender. I know the PacketAcknowledgements is recommended, but there are some questions I'm not sure about this interface.
1. If I use it in the sender mote,should i also uses interface Receive in the module of the sender mote
2. Should I write extra code in the receiver mote? Should I use interface PacketAcknowledgements too?
3. command error_t requestAck(message_t *msg) and command bool wasAcked(message_t *msg) should be used when and where
No.
No.
You need to call requestAck on a packet you're about to send just before calling send from interface AMSend or Send. Be sure to check an error code returned by requestAck, because FAIL indicates that the communication layer doesn't support synchronous acknowledgements (it depends on the radio chip and driver you use). Once the packet is sent, i.e., inside event sendDone (or later), call wasAcked, which returns true if the packet was acknowledged by the receiver.
More info in:
https://github.com/tinyos/tinyos-main/blob/master/tos/interfaces/PacketAcknowledgements.nc

How to Send a broadcast packet in a RDC layer in Contiki?

I'm trying to code my own RDC layer in contiki, with the PW-MAC protocol.
I was wondering how to send a broadcast in this layer because there will have no network and no transport layer.
The function i have to use will be:
NETSTACK_RDC.send(mac_callback_t sent, void *ptr)
But I really don't know what mac_callback_t and ptr is... The examples in sources use udp for the broadcast so it will be very annoying if i have to implement a transport layer.
Thanks for your answers
You should check a bit the doc and the code, that could help you a lot.
ptr is a data pointer (void*). So its your data to send.
mac_call_back_t is clear : to trigger a callback to the mac layer. (a function pointer)
To send a broadcast, just send to FFF address. (you must change the address with packetbuf, check the doc of packetbuf. (a good link for packet_buf : http://anrg.usc.edu/contiki/index.php/Packetbuffer_Basics)
Check the broadcast_conn in Rime to understand how broadcast are done and to have an example.
RDC stands for "radio duty cycling". The RDC layer uses radio functions directly, so sending a packet could be as simple as calling NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()).
The Contiki network stack has this layering structure:
NETWORK layer -> MAC layer -> RDC layer -> RADIO layer.
(In recent versions there's an additional LLSEC layer between NETWORK and MAC layers.)
So an implementation of RDC layer API uses the RADIO layer API and is called by / reports to MAC layer API. You can look at core/net/mac/nullrdc.c to see how to implement a simple RDC driver.
As you noted, NETSTACK_RDC.send(mac_callback_t sent, void *ptr) takes two parameters. The first is of callback type which you need to call after finishing the sending, the second is user data you need to pass to the to the callback.
The callback is typedef in net/mac/mac.h as:
typedef void (* mac_callback_t)(void *ptr, int status, int transmissions);
ptr is the user data pointer passed to NETSTACK_RDC.send;
status is MAC status code, such as MAC_TX_OK - the result of the
transmission;
transmissions is the number of transmissions.

get keyboard input contiki

I want to know how can I get a keyboard input in contiki os.
I already tried getchar(),getch(),scanf(),gets() and none worked, so I want to know if somebody can help me.
getchar,getch,scanf,gets are sort of POSIX things that read from files (e.g. stdin) --- these don't exist in Contiki (all though you could probably use them with the native platform).
So the first question to ask is what platform are you using and what do you mean by "keyboard". If keyboard means typing characters that are sent via a serial port from a computer then you have to know where they are received on the thing running Contiki. A typical arrangement is to receive characters on a uart, say, uart1.
In this case, contiki uses a callback such as uart1_input_handler that will be defined by the application. Platform main loops will check if there are characters to send to the input_handler and then check that an input_handler is defined. If so, will call something like uart1_input_handler(c).
You can see this code for the various platforms by grepping for uart1_input_handler:
platform/redbee-econotag/contiki-mc1322x-main.c: uart1_input_handler(uart1_getc());
cpu/msp430/dev/uart1x.c: if(uart1_input_handler(c)) {
cpu/stm32w108/dev/uart1.c: uart1_input_handler(c);
etc...
Some examples that register an input handler and process the characters:
example/shell:
/* set up the shell */
uart1_set_input(serial_line_input_byte);
serial_line_init();
serial_shell_init();
slip, in examples/ipv6/rpl-border-router/slip-bridge.c
slip_set_input_callback(slip_input_callback);
My guess for what you want to do would be to start with the shell examples and try to get those working.
The example cited below is from the Wiki pages of contiki on github. It demonstrates how the contiki specific mechanism for serial input works. Like mariano mentioned above that a callback has to be defined for the serial drivers specific to the platform you are using. I have used for ex. "rs232_set_input(RS232_PORT_0, serial_line_input_byte) ; " for my atmega128 MCU. The serial i/o drivers use this callback mechanism to post input characters to the "serial_line_process" defined in serial-line.c file. This process then broadcasts the serial_line_event_message to all processes along with the data read on the serial line. A process like the eg. stated below, can catch this event and process the input as per the requirements.
The callback mentioned above is defined in $(CONTIKI)/core/dev/serial-line.c. Check that out.
Once you initialise it using serial_line_init(), you are good to go.
#include "contiki.h"
#include "dev/serial-line.h"
#include <stdio.h>
PROCESS(test_serial, "Serial line test process");
AUTOSTART_PROCESSES(&test_serial);
PROCESS_THREAD(test_serial, ev, data)
{
PROCESS_BEGIN();
for(;;) {
PROCESS_YIELD();
if(ev == serial_line_event_message) {
printf("received line: %s\n", (char *)data);
}
}
PROCESS_END();
}
I assume you use COOJA (or maybe you connected a keyboard to your device so my answer will not be correct).
COOJA is an emulator, not a simulator.
If you want a responsive design, use the sensor button (on sky platform for example)
SENSORS_ACTIVATE(button_sensor);
/* Wait until we get a sensor event with the button sensor as data. */
PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event &&
data == &button_sensor);
Hope it helped.

Resources