Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • danc/MicroCART
  • snawerdt/MicroCART_17-18
  • bbartels/MicroCART_17-18
  • jonahu/MicroCART
4 results
Show changes
Showing
with 871 additions and 0 deletions
---
title: Decks
page_id: decks-index
---
Crazyflie expansion decks add new sensors and functionality to the Crazyflie. The firmware part of each deck is implemented as a [deck driver](/docs/development/howto.md) and adds functionality spcific to the deck. Read more about the functionality and implementation of each deck in the list below.
* [Active Marker deck](/docs/userguides/decks/active-marker-deck.md)
* [Micro-SD card deck](/docs/userguides/decks/micro-sd-card-deck.md)
* [Buzzer deck](/docs/userguides/decks/buzzer-deck.md)
---
title: Micro-SD card deck
page_id: micro-sd-card-deck
---
The microSD card deck allows to attach a micro SD card to the Crazyflie for reading and writing files. The default firmware additionally supports to use the uSD card for high-speed logging of [logging variables](/docs/userguides/logparam.md) at rates up to 1 kHz.
## Hardware
The specification of the deck can be found in the [wiki](https://wiki.bitcraze.io/projects:crazyflie2:expansionboards:microsd).
## File system
The SD-card used in the deck must be formatted as a FAT32 file system (exFAT does not work).
We use [FatFS](http://elm-chan.org/fsw/ff/00index_e.html) as the file system handler. Have a look at the API and examples on the FatFS site fore usage information.
The FatFS module will be initialized by the micro-SD deck driver when the deck is detected. After that the API calls can be used such as `f_mount`, `f_open`, `f_read`, `f_close` etc.
## Data Logging
Without any changes to `usddeck.c` there's a data logging functionality implemented. It can be enabled and configured by placing a config file on the µSD-Card. The file is a simple text file and an example is available [config.txt](https://github.com/bitcraze/crazyflie-firmware/blob/master/tools/usdlog/config.txt). The file format is as follows:
```
1 # version
512 # buffer size in bytes
log # file name
0 # enable on startup (0/1)
on:fixedFrequency
100 # frequency in Hz
1 # mode (0: disabled, 1: synchronous stabilizer, 2: asynchronous)
log entry 1
log entry 2
log entry 3
...
on:myEvent1
log entry 4
log entry 5
...
on:myEvent2
...
```
The config file supports logging of [log variables](/docs/userguides/logparam.md) as well as [event triggers](/docs/userguides/eventtrigger.md).
For the fixed frequency logging, the frequency is an integer value in Hertz, for example 250 means that a data block is written every 4ms. The buffer size is used to decouple the writing to the card and the data logging. Higher frequencies require a larger buffer, otherwise some data might be lost. The Crazyflie console will show how many events had to be discarded due to insufficient buffer size:
```
uSD: Wrote 161378 B to: log00 (2237 of 2237 events)
```
In general, logging 10 variables with 1kHz works well with a buffer of 512 Bytes. But you may have to try around a bit to get feeling on what is possible.
The file name should be 10 characters or less and a running number is appended automatically (e.g., if the file name is log, there will be files log00, log01, log02 etc.). The log entries are the names of logging variables in the firmware.
The `config.txt` file will be read only once on startup, therefore make sure that the µSD-Card is inserted before power up. If everything seems to be fine a µSD-task will be created and buffer space will be allocated. If malloc fails the Crazyflie will be stuck with LED M1 and M4 glowing. Data logging starts automatically after sensor calibration if `enable on startup` in `config.txt` was set to 1. Otherwise, logging can be started by setting the `usd.logging` parameter to 1. The logfiles will be enumerated in ascending order from 00-99 to allow multiple logs without the need of creating new config files. Just reset the Crazyflie to start a new file. Logging needs to be explicitly stopped by setting the `usd.logging` parameter to 0, which protects the logfile data with a CRC32.
## Data Analysis
For performance reasons the logfile is a binary file, using the following format (version 2):
```
uint8_t 0xBC header
uint16_t version
uint16_t num_event_types
for each event type:
uint16_t event_id
eventName<null>
uint16_t num_variables
varname1(vartype1)<null>varname2(vartype2)<null>...<null>varnameN(vartypeN)<null>
for each event:
uint16_t event_id
uint64_t timestamp (in microseconds)
data (length defined by TOC event type)
```
Here, the vartype is a singe character and we support a subset of the ones defined [here](https://docs.python.org/3/library/struct.html#format-characters).
We provide a [helper script](https://github.com/bitcraze/crazyflie-firmware/blob/master/tools/usdlog/cfusdlog.py) to decode the data:
```
import cfusdlog
logData = cfusdlog.decode(fileName)
```
where fileName is a file from the µSD-Card. For convenience there is also an [example.py](https://github.com/bitcraze/crazyflie-firmware/blob/master/tools/usdlog/example.py) which shows how to access and plot the data.
## Alternate Pins
The SD-Card is using the SPI bus on the deck port to communicate. In some cases, it might be beneficial to use another SPI bus. One option is to use a "hidden" SPI on the deck port that is multiplexed with TX1, RX1 and IO_4. This SPI port is called SPI3 in the STM32F405 and there is a possibility to switch to this SPI bus.
- First thing the SD-card deck needs to be patched, CS->RX2(PA3), SCLK->TX1(PC10), MISO->RX1(PC11), MOSI->IO_4(PC12) and this is a quite hard to cut the small lines and solder small patch wires. Easier is to use a sd-card breakout deck such as [this](https://www.sparkfun.com/products/544) and solder wires to e.g. the battery holder board.
- Compile the firmware with `CFLAGS += -DUSDDECK_USE_ALT_PINS_AND_SPI` in your config.mk file.
- If you want to use the Loco-deck at the same time, the alternative pins for this must be used. This means cutting GS1 and GS2 underneath the loco-deck and soldering the bridged GS3 and GS4. Then add `CFLAGS += -DLOCODECK_USE_ALT_PINS` to you config.mk as well.
---
title: Event Trigger framework
page_id: eventtrigger
---
The aim of the event trigger framework is to be able to log events and their payloads
synchronously. Thus, event triggers are closely related to the [Logging Framework](/docs/userguides/logparam.md), which
logs data asynchronously. One key use-case of the event trigger framework is to analyze different state estimators.
For each measurement that is pushed into the current state estimator, an event with the appropriate payload containing
the measurement can be stored for later analysis.
## Add Event Triggers in the Firmware
In order to add a new event trigger named `myEvent` with a payload of two variables, you have to add the following near the top of your *.c file:
``` {.c}
#include "eventtrigger.h"
// declares eventTrigger_myEvent and eventTrigger_myEvent_payload
EVENTTRIGGER(myEvent, uint8, var1, float, var2)
```
The EVENTTRIGGER macro is variadic, i.e. it can take a varying number of arguments. It is also valid to have a event trigger without any payload.
Internally, the macro generates code that declares several static variables. Details can be found in [eventtrigger.h](https://github.com/bitcraze/crazyflie-firmware/blob/master/src/modules/interface/eventtrigger.h).
Once the event trigger is defined, it can be triggered anywhere in the source code of the same *.c file:
``` {.c}
// set the payload
eventTrigger_myEvent_payload.var1 = some_value_related_to_the_event;
eventTrigger_myEvent_payload.var2 = another_value_related_to_the_event;
// trigger the event
eventTrigger(&eventTrigger_myEvent);
```
Users can configure to log additional regular logging variables for each event, so the payload should be limited to mandatory data that identifies the event.
For example, if a new measurement is enqueued in the state estimator, the actual measurement should be included as payload, while the (constant) standard deviation
should not be part of it.
## Using Event Triggers
Currently, the only backend for event triggers is the uSD-card deck. You can find a description of how to configure
and analyze the events in its [documentation](/docs/userguides/decks/micro-sd-card-deck.md).
---
title: Logging and parameter frameworks
page_id: logparam
---
The aim of the logging and parameter framework is to easily be able to
log data from the Crazyflie and to set variables during runtime.
## Table of content (TOC)
The variables that are available for the logging/parameter framework is
decided on compile-time for the Crazyflie firmware. Using C macros
variables can be made available to the framework below are two examples,
one for parameters and one for logging.
A parameter or logging variable that is created with `PARAM_ADD_CORE` or `LOG_ADD_CORE` is considered stable API and will with a very high likelihood be available a cross firmware versions. All core parameters and logging variables must have documentation associated with it. See below for examples of the documentation syntax.
This will make the parameters used to control the [LED-ring
expansion](https://www.bitcraze.io/products/led-ring-deck/) available as
parameters. Note that they have different types and that *neffect* is
read-only.
``` {.c}
/**
* [Documenation for the ring group ...]
*/
PARAM_GROUP_START(ring)
/**
* @brief [Documentation for the parameter below ...]
*/
PARAM_ADD_CORE(PARAM_UINT8, effect, &effect)
/**
* @brief [Documentation for the parameter effect ...]
*/
PARAM_ADD_CORE(PARAM_UINT32 | PARAM_RONLY, neffect, &neffect)
/**
* @brief [Documentation for the parameter effect ...]
*/
PARAM_ADD_CORE(PARAM_UINT8, solidRed, &solidRed)
[...]
PARAM_ADD(PARAM_FLOAT, emptyCharge, &emptyCharge)
PARAM_ADD(PARAM_FLOAT, fullCharge, &fullCharge)
PARAM_GROUP_STOP(ring)
```
This will make the variables for roll/pitch/yaw/thrust available for the
logging framework. These are the variables used to fill in the data in
the [Python cfclient FlightTab](https://www.bitcraze.io/documentation/repository/crazyflie-clients-python/master/userguides/userguide_client/).
/**
* [Documentation for the stabilizer group ...]
*/
LOG_GROUP_START(stabilizer)
/**
* @brief [Documentation for variable below ...]
*/
LOG_ADD_CORE(LOG_FLOAT, roll, &eulerRollActual)
/**
* @brief [Documentation for variable below ...]
*/
LOG_ADD_CORE(LOG_FLOAT, pitch, &eulerPitchActual)
/**
* @brief [Documentation for variable below ...]
*/
LOG_ADD_CORE(LOG_FLOAT, yaw, &eulerYawActual)
/**
* @brief [Documentation for variable below ...]
*/
LOG_ADD_CORE(LOG_UINT16, thrust, &actuatorThrust)
LOG_GROUP_STOP(stabilizer)
During the compilation a table of content (TOC) is created that holds
all the available variables together with the type and access
restrictions. There\'s one TOC for each framework, one for logging and
one for parameters. When the client connects it will download the TOC to
know which variables can be used. It\'s then easy to use the [Python
API](https://github.com/bitcraze/crazyflie-lib-python) ([or another
API](https://wiki.bitcraze.io/doc:crazyflie:api:community) for accessing them.
All the variables have a name and belong to a group. So in the examples
above there\'s two groups defined: *ring* and *stabilizer*. To refer to
a variable use the naming convention *group.name*. If you would like to
log the *roll* variable in the *stabilizer* group it\'s access by
*stabilizer.roll*. And if you would like to set the *effect* variable in
the ring group it\'s accessed using *ring.effect*.
## Parameters
Using the parameter framework it\'s possible to both read and write
variables in run-time, but note the following:
- There\'s no thread protection on reading/writing. Since the
architecture is 32bit and the largest parameter you can have is
32bit it\'s safe to write one variable. But if you write a group of
variables that should be used together (like PID parameters) you
might end up in trouble.
- Only use the parameter framework to read variables that are set
during start-up. If variables change during runtime then use the
logging framework.
- The reading or writing of a parameter can be done at any time once
you are connected to the Crazyflie.
## Logging
The logging framework is used to log variables from the Crazyflie at a
specific interval. Instead of triggering a reading of the variables at
certain intervals, the framework is used to set up a logging
configuration to that will push data from the Crazyflie to the host.
After the host has connected to a Crazyflie and downloaded the TOC it
will be possible to setup one of these configurations. Once the
configuration is set up and started the Crazyflie will start pushing
data to the host. A configuration can be stopped and re-started again.
Since there\'s a finite amount of memory a configuration can be deleted
to make room for new ones.
Note the following for the logging framework:
- Once a Crazyflie is connected you can set up new logging
configurations. It\'s only possible to create/start/stop/remove
configurations that\'s already created.
- The interval for a logging configuration is specified in 10th of
milliseconds.
Note that variables can be logged as different types from what they have
been declared as in the firmware. I.e if a variable is declared as a
uint32\_t you can log it as a uint8\_t (this is being done for the
motors in the UI).
### Logging using a function
It is possible to use a function to acquire log values instead of
reading from a memory location. The idea is to support more complex use cases
where, for instance computations are required to produce the log value.
The macro
```LOG_ADD_BY_FUNCTION(TYPE, NAME, ADDRESS)```
is used to add a log to a group. ```TYPE``` and ```NAME``` works the same way as for variable logging, but
```ADDRESS``` should point at a logByFunction_t struct instead of a variable. The struct contains
a function pointer to the function to call when acquiring data, as well as
a void pointer with user data passed that is passed on in the function call.
Example:
float myLogValueFunction(uint32_t timestamp, void* data) {
// Return the log value
return 47.11;
}
logByFunction_t myLogger = {.aquireFloat = myLogValueFunction, .data = 0};
LOG_GROUP_START(myGroup)
LOG_ADD_BY_FUNCTION(LOG_FLOAT, myLog, &myLogger)
LOG_GROUP_STOP(myGroup)
Note: The logging function is only called if the log is part of an active log configuration. It
will be called (approximately) at the interval that is setup in the log configuration.
### Logging rates
A common usecase is to log rates (events / s) and there are a set of macros to simplify this task.
The rate logger uses a struct to store data, it is called ```statsCntRateCounter_t``` and
is initialize using the ```STATS_CNT_RATE_INIT```macro. The struct contains a counter, time
information and the latest calculated rate. The initialization macro takes a parameter
that specifies the update interval (in ms) and defines how often the rate (delta count / delta time)
is calculated. The update interval should match the expected event rate to give meaningful results.
With the ```STATS_CNT_RATE_DEFINE``` macro, the struct can be defined and initialized in one line.
To register an event, that is to increase the counter, use the ```STATS_CNT_RATE_EVENT```macro.
Register the rate counter in a log group witht the ```STATS_CNT_RATE_LOG_ADD``` macro.
Example:
static const uint32_t one_second = 1000;
static statsCntRateLogger_t myCounter;
static STATS_CNT_RATE_DEFINE(myOtherCounter, one_second);
void myInit() {
STATS_CNT_RATE_INIT(&myCounter, one_second);
}
void theFcnThatIWantTheCallRateFor() {
...
STATS_CNT_RATE_EVENT(&myCounter);
...
STATS_CNT_RATE_EVENT(&myOtherCounter);
}
LOG_GROUP_START(myGroup)
// The logging type is implicitly LOG_FLOAT
STATS_CNT_RATE_LOG_ADD(rtCall, &myCounter)
STATS_CNT_RATE_LOG_ADD(rtCall2, &myOtherCounter)
LOG_GROUP_STOP(myGroup)
Note: The rate computation function is called from the logging framework with the interval
specifed in the logging configuration. The rate, on the other hand, is calculated if the time since
last computation exceeds the configured update time of the rate logger, and if the logging intervall
is longer than the update intervall, updates will be done for each logging call.
bin/*
cf2.*
# enable app support
APP=1
APP_STACKSIZE=300
VPATH += src/
PROJ_OBJ += appchannel_test.o
CRAZYFLIE_BASE=../..
include $(CRAZYFLIE_BASE)/Makefile
\ No newline at end of file
# Appchannel test app for Crazyflie 2.x
This application demonstrates how to use the appchannel API to send and receive
radio packets between a Crazyflie app and the python lib.
This demo defines a protocol where the Crazyflie waits for 3 floas (x, y, z) and sends back the sum as one float.
To run this example, compile and flash the app with ```make && make cload```.
When the Crazyflie is flashed and started, you can run the python example with ```python3 tools/appchannelTest.py```.
\ No newline at end of file
/**
* ,---------, ____ _ __
* | ,-^-, | / __ )(_) /_______________ _____ ___
* | ( O ) | / __ / / __/ ___/ ___/ __ `/_ / / _ \
* | / ,--´ | / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
* +------` /_____/_/\__/\___/_/ \__,_/ /___/\___/
*
* Crazyflie control firmware
*
* Copyright (C) 2019 Bitcraze AB
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, in version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* appchanel_test.c: Demonstrate the appchanel functionality
*/
#include "app.h"
#include "app_channel.h"
#include "debug.h"
#define DEBUG_MODULE "HELLOWORLD"
struct testPacketRX {
float x;
float y;
float z;
} __attribute__((packed));
struct testPacketTX {
float sum;
} __attribute__((packed));
void appMain()
{
DEBUG_PRINT("Waiting for activation ...\n");
struct testPacketRX rxPacket;
struct testPacketTX txPacket;
while(1) {
if (appchannelReceivePacket(&rxPacket, sizeof(rxPacket), APPCHANNEL_WAIT_FOREVER)) {
DEBUG_PRINT("App channel received x: %f, y: %f, z: %f\n", (double)rxPacket.x, (double)rxPacket.y, (double)rxPacket.z);
txPacket.sum = rxPacket.x;
txPacket.sum += rxPacket.y;
txPacket.sum += rxPacket.z;
appchannelSendPacket(&txPacket, sizeof(txPacket));
}
}
}
\ No newline at end of file
# -*- coding: utf-8 -*-
#
# || ____ _ __
# +------+ / __ )(_) /_______________ _____ ___
# | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \
# +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
# || || /_____/_/\__/\___/_/ \__,_/ /___/\___/
#
# Copyright (C) 2014 Bitcraze AB
#
# Crazyflie Nano Quadcopter Client
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
"""
Simple example that connects to the first Crazyflie found, Sends and
receive appchannel packets
The protocol is:
- 3 floats are send, x, y and z
- The Crazyflie sends back the sum as one float
"""
import logging
import time
from threading import Thread
import struct
import cflib
from cflib.crazyflie import Crazyflie
logging.basicConfig(level=logging.ERROR)
class AppchannelTest:
"""Example that connects to a Crazyflie and ramps the motors up/down and
the disconnects"""
def __init__(self, link_uri):
""" Initialize and run the example with the specified link_uri """
self._cf = Crazyflie()
self._cf.connected.add_callback(self._connected)
self._cf.disconnected.add_callback(self._disconnected)
self._cf.connection_failed.add_callback(self._connection_failed)
self._cf.connection_lost.add_callback(self._connection_lost)
self._cf.appchannel.packet_received.add_callback(self._app_packet_received)
self._cf.open_link(link_uri)
print('Connecting to %s' % link_uri)
def _connected(self, link_uri):
""" This callback is called form the Crazyflie API when a Crazyflie
has been connected and the TOCs have been downloaded."""
# Start a separate thread to do the motor test.
# Do not hijack the calling thread!
Thread(target=self._test_appchannel).start()
def _connection_failed(self, link_uri, msg):
"""Callback when connection initial connection fails (i.e no Crazyflie
at the specified address)"""
print('Connection to %s failed: %s' % (link_uri, msg))
def _connection_lost(self, link_uri, msg):
"""Callback when disconnected after a connection has been made (i.e
Crazyflie moves out of range)"""
print('Connection to %s lost: %s' % (link_uri, msg))
def _disconnected(self, link_uri):
"""Callback when the Crazyflie is disconnected (called in all cases)"""
print('Disconnected from %s' % link_uri)
def _app_packet_received(self, data):
(sum, ) = struct.unpack("<f", data)
print(f"Received sum: {sum}")
def _test_appchannel(self):
for i in range(10):
(x, y, z) = (i, i+1, i+2)
data = struct.pack("<fff", x, y, z)
self._cf.appchannel.send_packet(data)
print(f"Sent x: {x}, y: {y}, z: {z}")
time.sleep(1)
self._cf.close_link()
if __name__ == '__main__':
# Initialize the low-level drivers (don't list the debug drivers)
cflib.crtp.init_drivers(enable_debug_driver=False)
# Scan for Crazyflies and use the first one found
print('Scanning interfaces for Crazyflies...')
available = cflib.crtp.scan_interfaces()
print('Crazyflies found:')
for i in available:
print(i[0])
if len(available) > 0:
le = AppchannelTest(available[0][0])
else:
print('No Crazyflies found, cannot run example')
bin/*
cf2.*
# enable app support
APP=1
APP_STACKSIZE=300
VPATH += src/
PROJ_OBJ += hello_world.o
CRAZYFLIE_BASE=../..
include $(CRAZYFLIE_BASE)/Makefile
\ No newline at end of file
# Hello world App for Crazyflie 2.X
This folder contains the app layer application for the Crazyflie to print a hello world debug message, which can be read in the console tab of the [cfclient](https://github.com/bitcraze/crazyflie-clients-python).
See App layer API guide [here](https://www.bitcraze.io/documentation/repository/crazyflie-firmware/master/userguides/app_layer/)
## Build
Make sure that you are in the app_hello_world folder (not the main folder of the crazyflie firmware). Then type the following to build and flash it while the crazyflie is put into bootloader mode:
```
make clean
make
make cload
```
If you want to compile the application elsewhere in your machine, make sure to update ```CRAZYFLIE_BASE``` in the **Makefile**.
\ No newline at end of file
/**
* ,---------, ____ _ __
* | ,-^-, | / __ )(_) /_______________ _____ ___
* | ( O ) | / __ / / __/ ___/ ___/ __ `/_ / / _ \
* | / ,--´ | / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
* +------` /_____/_/\__/\___/_/ \__,_/ /___/\___/
*
* Crazyflie control firmware
*
* Copyright (C) 2019 Bitcraze AB
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, in version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* hello_world.c - App layer application of a simple hello world debug print every
* 2 seconds.
*/
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "app.h"
#include "FreeRTOS.h"
#include "task.h"
#include "debug.h"
#define DEBUG_MODULE "HELLOWORLD"
void appMain()
{
DEBUG_PRINT("Waiting for activation ...\n");
while(1) {
vTaskDelay(M2T(2000));
DEBUG_PRINT("Hello World!\n");
}
}
\ No newline at end of file
# enable app support
APP=1
APP_STACKSIZE=300
VPATH += src/
PROJ_OBJ += internal_log_param_api.o
CRAZYFLIE_BASE=../..
include $(CRAZYFLIE_BASE)/Makefile
\ No newline at end of file
# Internal parameters and loggin api App example for Crazyflie 2.X
This folder contains the app layer application for the Crazyflie to use the internal logging and parameter API, which can be monitord in the console tab of the [cfclient](https://github.com/bitcraze/crazyflie-clients-python).
See App layer API guide [here](https://www.bitcraze.io/documentation/repository/crazyflie-firmware/master/userguides/app_layer/)
## Build
Make sure that you are in the app_hello_world folder (not the main folder of the crazyflie firmware). Then type the following to build and flash it while the crazyflie is put into bootloader mode:
```
make clean
make
make cload
```
If you want to compile the application elsewhere in your machine, make sure to update ```CRAZYFLIE_BASE``` in the **Makefile**.
\ No newline at end of file
/**
* ,---------, ____ _ __
* | ,-^-, | / __ )(_) /_______________ _____ ___
* | ( O ) | / __ / / __/ ___/ ___/ __ `/_ / / _ \
* | / ,--´ | / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
* +------` /_____/_/\__/\___/_/ \__,_/ /___/\___/
*
* Crazyflie control firmware
*
* Copyright (C) 2019 Bitcraze AB
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, in version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* internal_log_param_api.c - App layer application of the internal log
* and param api
*/
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "app.h"
#include "FreeRTOS.h"
#include "task.h"
#include "debug.h"
#include "log.h"
#include "param.h"
#define DEBUG_MODULE "INTERNLOGPARAM"
void appMain()
{
DEBUG_PRINT("This is the App layer example of the internal log param api...\n");
logVarId_t idYaw = logGetVarId("stateEstimate", "yaw");
float yaw = 0.0f;
paramVarId_t idEstimator = paramGetVarId("stabilizer", "estimator");
uint8_t estimator_type = 0;
while(1) {
vTaskDelay(M2T(2000));
// Get the logging data
yaw = logGetFloat(idYaw);
DEBUG_PRINT("Yaw is now: %f deg\n", (double)yaw);
// Get parameter value
estimator_type = paramGetInt(idEstimator);
DEBUG_PRINT("Estimator type is now: %d deg\n", estimator_type);
// Set a parameter value
// Note, this will influence the flight quality if you change estimator
uint8_t new_value = 2;
paramSetInt(idEstimator, new_value);
}
}
\ No newline at end of file
bin/*
cf2.*
# enable app support
APP=1
APP_STACKSIZE=300
VPATH += src/
PROJ_OBJ += peer_to_peer.o
CRAZYFLIE_BASE=../..
include $(CRAZYFLIE_BASE)/Makefile
\ No newline at end of file
# Peer to Peer App for Crazyflie 2.X
This folder contains the app layer application for the Crazyflie to send and receive peer to peer messages. The debug messages of the received messages can be read in the console tab of the [cfclient](https://github.com/bitcraze/crazyflie-clients-python). Two Crazyflies need to be flashed with this program in order to work. Make sure that they are both on the same channel, and that they have different IDs.
This example is going to blink the M4 LED when packets are sent and received, if you run 2 Crazyflies with this example you should see M4 blinking red and green in sequence indicating bidirectional P2P communication.
You can find on Bitcraze's website the [API documentation for P2P](https://www.bitcraze.io/documentation/repository/crazyflie-firmware/master/functional-areas/p2p_api/) as well as the [App layer API guide](https://www.bitcraze.io/documentation/repository/crazyflie-firmware/master/userguides/app_layer/)
## Limitations
Since P2P communication happens asynchronously on the radio, this example does not work well when connecting a PC to the Crazyflies via the Radio. You should connect the Crazyflies using the USB port. This is a fundamental limitation of the current P2P implementation.
## Build
Make sure that you are in the app_peer_to_peer folder (not the main folder of the crazyflie firmware). Then type the following to build and flash it while the crazyflie is put into bootloader mode:
```
make clean
make
make cload
```
If you want to compile the application elsewhere in your machine, make sure to update ```CRAZYFLIE_BASE``` in the **Makefile**.
/**
* ,---------, ____ _ __
* | ,-^-, | / __ )(_) /_______________ _____ ___
* | ( O ) | / __ / / __/ ___/ ___/ __ `/_ / / _ \
* | / ,--´ | / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
* +------` /_____/_/\__/\___/_/ \__,_/ /___/\___/
*
* Crazyflie control firmware
*
* Copyright (C) 2019 Bitcraze AB
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, in version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* peer_to_peer.c - App layer application of simple demonstartion peer to peer
* communication. Two crazyflies need this program in order to send and receive.
*/
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include "app.h"
#include "FreeRTOS.h"
#include "task.h"
#include "radiolink.h"
#include "configblock.h"
#define DEBUG_MODULE "P2P"
#include "debug.h"
#define MESSAGE "hello world"
#define MESSAGE_LENGHT 11
void p2pcallbackHandler(P2PPacket *p)
{
// Parse the data from the other crazyflie and print it
uint8_t other_id = p->data[0];
static char msg[MESSAGE_LENGHT + 1];
memcpy(&msg, &p->data[1], sizeof(char)*MESSAGE_LENGHT);
msg[MESSAGE_LENGHT] = 0;
uint8_t rssi = p->rssi;
DEBUG_PRINT("[RSSI: -%d dBm] Message from CF nr. %d, %s\n", rssi, other_id, msg);
}
void appMain()
{
DEBUG_PRINT("Waiting for activation ...\n");
// Initialize the p2p packet
static P2PPacket p_reply;
p_reply.port=0x00;
// Get the current address of the crazyflie and obtain
// the last two digits and send it as the first byte
// of the payload
uint64_t address = configblockGetRadioAddress();
uint8_t my_id =(uint8_t)((address) & 0x00000000ff);
p_reply.data[0]=my_id;
//Put a string in the payload
char *str="Hello World";
memcpy(&p_reply.data[1], str, sizeof(char)*MESSAGE_LENGHT);
// Set the size, which is the amount of bytes the payload with ID and the string
p_reply.size=sizeof(char)*MESSAGE_LENGHT+1;
// Register the callback function so that the CF can receive packets as well.
p2pRegisterCB(p2pcallbackHandler);
while(1) {
// Send a message every 2 seconds
// Note: if they are sending at the exact same time, there will be message collisions,
// however since they are sending every 2 seconds, and they are not started up at the same
// time and their internal clocks are different, there is not really something to worry about
vTaskDelay(M2T(2000));
radiolinkSendP2PPacketBroadcast(&p_reply);
}
}