nRF24 - data received but not whole message - c

Here is the setup. Arduino #1 has a w5100 ethernet shield running a webserver accepting GET strings. It then parses out the data and sends it wirelessly to the other nodes using nRF24l10 transceivers. I'm using maniacbug's RF24 and RF24Network libraries. Also due to having the ethernet shield and the wireless I had to use a modified RF24 for the base that supports soft SPI.
Arduino #2 is just the nRF24L10.
What is working. Sending GET's to Arduino #1 works. It parses the information. It then calls the send routine and that says it's ok.
On arduino #2 I get a "Received:" printout but no message. I'm not sure what is wrong. The code is taken right from maniacbug's tx and rx example. Except I had to convert my sendString to a char to send.
I'm wondering if it's one of the following things but I'm not quite sure how to debug.
That the addition of the RF24Network library broke the softSPI. I've been very careful to remove one libray and add the other when I compile. Though if this were the case I'd never see the "Received:" would i?
It doesn't like my conversion from string to char?
Here is the code.
Base Station: http://pastebin.com/Ehy8pz4Z
Receiver : http://pastebin.com/2mz9FjsR
Here is the modified RF24+ softspi library. https://github.com/shnae/rf24_plus_softSPI if that helps.
I don't think just adding the nrf24network library breaks that but since it calls SPI.begin() it might. That's beyond my skillset..

So as it turns out you need to put network.update(); in loop.... If you only call it per request like I did it will not work. Hence the //do this regularly comment that you see for this.

Related

Stm32 Log Messages

good day, stm32 nucleo board I want to write informative Log messages using.
For example, I want to display the message that the program has started by using the Log("Program started") function when the program starts during this period, or I want to give the error message to the screen by using the Log("Program Failed') function when the program fails.
I using C programming langue and stm32cubeide & Nucleo f207zg board thanks in advance for your help
Thanks I solved the problem
Given that:
You know what the UART/USART peripheral is
You connected the right pins to a serial interface
You connected the other end of the interface (for instance an FTDI chip) to your computer
You can implement the logging with printf as you would do in C. Why? Because printf already takes care for you the formatting of the strings, which no one wants to reimplement, and then you redirect the printf output to the UART peripheral that handles low level serial protocol.
Following this guide the steps are easy enough:
Add #include <stdio.h> to the Includes section at the top of the main.c
#include "stdio.h"
Copy and paste the following code into the main.c file before the main() function but after the UART handle declaration
Note that you need to replace the question mark with the actual UART handle declaration, for instance huart1
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart?, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
As pointed out by Fra93, you need to implement UART/USART protocol communication and print stuff to there. I'm writing this reply, because I'm getting a feeling you have some basic experience writing desktop applications, but not embedded, so I will clarify a few points.
There is no console to print to. There are no logs. They simply don't exist. At all. Not in a desktop app development sense.
What's usually done is that one of the UARTs of the MCU is used to print characters to the ST-Link, which converts it to USB (alternatively, can be FTDI IC, CP2102 or other USB-UART bridges/converters). So then your MCU will send out characters over UART, and the USB-UART converter will display them in a COM port terminal (programs like PuTTy)
If you start with empty project and no external libraries used, you will need 3 dozen lines of code alone just to be able to print stuff. Initially, you have nothing. You have to initialize UART, configure it, then implement how it handles characters, numbers. You need to literally write a basic UART driver. And you can call printing function whatever you want. You can call it Log("hello world"), you can call it Whisper("hi there"). Because you will actually create this function. You're the boss.
Now, given you are not very familiar with all of this, it may sound like a difficult task. And it most certainly is. Writing a driver from scratch on your day 1 is not a thing you want to do (unless you're into that kind of stuff on day 1).
I would strongly advise you to get some library, such as HAL by STMicroelectronics, and familiarize yourself with what it can do - including how to print stuff with UART. Internet is flooded with articles and videos of how to use UART with HAL, it's literally one of the first things to be implemented. Specifically for the reason, that it works like logs and simplifies further development/learning.
So, in order to get "logs" working, I would do the following:
Get HAL for your specific MCU
Familiarize yourself with UART - basic stuff about what it is and how it works. No need to be an expert, just learn what it is.
Familiarize yourself with how to use UART with HAL
From the schematic of the PCB of your nucleo board, find out which UART of the MCU is connected to ST-Link (I checked the schematic: it's USART3)
Get serial port (COM) terminal program for your computer
Use HAL to initialize USART3 and print to USART3. Whatever you print there will be visible in the terminal. Yes, you will not see anything in the IDE. You need a separate program to display what you receive via USB COM port.
In the end, your print function will be the one proposed by Fra93. HAL_UART_Transmit is the most basic HAL function to send stuff via UART. If you're very picky about using "Log" as a function you call to print via UART, you can always wrap HAL_UART_Transmit into your own function called Log.

Targeting an Xbee using AT Commands Mode

I am trying to get one Xbee to talk to another. I understand that I can use putc to broadcast to all Xbees on a network but I want to target one specifically. I know that I need to use the hardware address on the XBee to do this and by using something called AT Commands mode but I don't think I understand it. For example, I have seen that to get into AT Commands mode I need to send '+++', however, I don't understand what to do. I tried this:
xbee.printf('+++');
but don't know where to look for some kind of message in response.
I don't understand this mode and can't seem to find anything which gives me an example for my situation or a relevant one.
I am using a normal Xbee on an FRDM-K64F.
Worked it out.
To do this, you first need to do:
xbee.printf("xxx");
This puts you into AT Command mode and you can then run AT Commands. You need to wait at least 1 second before and after going into AT Command mode for this to work:
wait(1)
To send to a specific Xbee, you need it's 16-bit address and this can be found from the underside of the Xbee (although there is an AT Command to get this). The first 8-bits are the Xbee's high address (this is the same for all Xbees) and the second is it's low address and you need to set both of these using AT Commands before sending to the specific Xbee will work. To set these you must do the following:
xbee.printf("atdh 0013A200\n\r");
xbee.printf("atdl 12345678\n\r");
You must do the \n\r part as this simulates an Enter button press which is needed to actually run the command.
The atdh command sets the high address and the atdl command sets the low address. Once this is done, your sending Xbee will be configured to send to a specific Xbee and will not broadcast to all on the network. So when you now do:
xbee.putc('Y');
it will go to the Xbee who's address you have set.
You may have to wait 10 seconds after running those commands because I don't think I/O works in AT Command mode (I have not worked out yet how to exit AT Command mode yet but will update when I do).

Spi interrupt handler works when a printf() is used

I am trying to initiate a spi communication between an omap processor an sam4l one. I have configured spi protocol and omap is the master. Now what I see is the test data I am sending is correctly reaching on sam4l and I can see the isr is printing that data. Using more printf here and there in isr makes the operation happen and the respective operation happens, but if I remove all printfs I can't see any operation happening. What can be the cause of this anomaly? Is it a usual case of wrong frequency settings or something?
If code is needed I will post that too but its big.
Thanks
I think you are trying to print message in driver.
As printing message on console with slow down your driver, it may behave slowly and your driver work well.
Use pr_info() for debug and change setting to not come message on console by editing /proc/sys/kernel/printk to 4 4 1 7
-> It will store debug message in buffer.
-> Driver not slow down because of printing message on screen.
-> And you can see it by typing dmesg command later.
Then find orignal problem which may cause error.
If a routine works with printf "here and there" and not otherwise, almostcertainly the problem is that there are timing issues. As a trivial example, let's say you write to an SPI flash and then check its content. The flash memory write will take some times, so if you check immediately, the data would not be valid, but if you insert a printf call in between, it may have taken enough time that the read back is now valid.

Is it possible to write a packet, read by libpcap, with libnet? in c?

I'm trying to get libpcap to read a pcap file, get the user to select a packet and write that packet using libnet, in c.
I got the reading from file part done. Libpcap puts that packet into a const unsigned char. I have worked with libnet before, but never with libnet's advanced functions. I would just create the packet using libnet's build functions, then let them on their way. I realize there is a function, libnet_adv_write_link() that takes the libnet context, a pointer to a packet to inject(const uint8_t) and the size of the packet. I tried passing the 'packet' that I got from libpcap, and it compiled and executed without errors. However, I am not seeing anything in wireshark.
Would this be the right way to tackle this problem, or should I read from libpcap and build a separate packet with libnet, based on what libpcap read?
EDIT: I believe I somewhat solved the problem. I read the packet with libpcap. Put all the bytes after the 16th byte into another uchar and wrote that into the wire. using libnet_adv_write_raw_ipv4(), libnet initialized with LIBNET_RAW4_ADV. I believe, maybe because of the driver, I don't have much power over the ETH layer. so basically I just let it be written automatically this way, and the new uchar packet is just whatever is left after the ETH layer in the original packet. Works fine so far.
I'm the current libnet maintainer.
You should call libnet_write_link() to write a packet. If you aren't seeing it, its possible you haven't opened the correct device, that you lack permissions (you checked the return value of libnet_write_link I hope), and also possible that the packet injected was invalid.
If you don't need to build the packet, it sounds like you should be using pcap to send the packet, though, see http://www.tcpdump.org/manpages/pcap_inject.3pcap.html
Also, your statement "Libpcap puts that packet into a const unsigned char" is odd. A packet doesn't fit in a single char, what pcap does is, depending on the API, return pointers into the packet data. Its worth including a snippet of code showing how you get the packet from data, and how you pass it to libnet. Its possible you aren't using the pointers correctly.
If you are using libpcap, why not use libpcap to send the packet? No, it's not well known, but yes it does work. See the function pcap_sendpacket.
The packet libpcap returns is simply an array of bytes. Anything that takes an array of bytes (including the ethernet frame) should work. However, note that your OS and/or hardware may stop you from sending packets with incorrect or malformed source MAC addresses.

Receive message of undefined size in UART in C

I'm writing my own drivers for LPC2148 and a question came to mind.
How do I receive a message of unspecified size in UART?
The only 2 things that come to mind are: 1 - Configure a watchdog and end the receiving when the time runs out. 2- make it so that whenever a meswsage is sent to it there must be an end of message character.
The first choice seems better in my opinion, but I'd like to know if anybody has a better answer, and I know there must be.
Thank you very much
Just give the caller whatever bytes you have received so far. The UART driver shouldn't try to implement the application protocol, the application should do that.
It looks like a wrong use for a watchdog. I ended up with three solutions for this problem:
Use fixed-size packets and DMA; so, you receive one packet per transaction. Apparently, it is not possible in your case.
Receive message char-by-char until the end-of-message character is received. Kind of error-prone, since the EOM char may appear in the data, probably.
Use a fixed-size header before every packet. In the header, store payload size and/or message type ID.
The third approach is probably the best one. You may combine it with the first one, i.e. use DMA to receive header and then data (in the second transaction, after the data size is known from the header). It is also one of the most flexible approaches.
One more thing to worry about is to keep bytestream in sync. There may be rubbish laying in the UART input buffers, which may get read as data, or you can get only a part of a packet after your MCU is powered (i.e. the beginning of the packet had already been sent by that time). To avoid that, you can add magic bytes in your packet header, and probably CRC.
EDIT
OK, one more option :) Just store everything you receive in a growing buffer for later use. That is basically what PC drivers do.
Real embedded uart drivers usually use a ring buffer. Bytes are stored in order and the clients promise to read from the buffer before it's full.
A state machine can then process the message in multiple passes with no need for a watchdog to tell it reception is over
better to go for option 2) append end of transmission character to the transmission string.
but i suggest to add start of transmission also to validate that you are receiving actual transmission.
Watchdog timer is used to reset system when there is a unexpected behavior of device. I think it is better to use a buffer which can store size of data that your application requires.

Resources