I am making a fairly simple script for sound on my arduino. Here's my script:
#include <digitalWriteFast.h>
struct AudioHandler {
//Alter these as you require
const int pin = 2;
float frequency = 1;
float dutyCycle = 1;
//These are internal variables that you shouldn't touch
unsigned long prevMicros = 0;
bool onHalf = true; //This just asks which half of the wave the sound is on
//This just checks the time and asks if it should switch to the other half of the wave
void updateSound() {
if ((micros() - prevMicros > (1000000 / frequency) * dutyCycle) && (onHalf)) {
prevMicros = micros();
onHalf = false;
digitalWriteFast(pin,false);
} else if ((micros() - prevMicros > (1000000 / frequency) * (1 - dutyCycle)) && (!onHalf)) {
prevMicros = micros();
onHalf = true;
digitalWriteFast(pin,true);
}
}
};
AudioHandler test_1;
AudioHandler test_2;
AudioHandler test_3;
AudioHandler test_4;
void setup() {
pinModeFast(3,OUTPUT); test_1.frequency = 65.41; test_1.dutyCycle = 0.5;
pinModeFast(4,OUTPUT); test_2.frequency = 82.41; test_2.dutyCycle = 0.5;
pinModeFast(5,OUTPUT); test_3.frequency = 98.00; test_3.dutyCycle = 0.5;
pinModeFast(6,OUTPUT); test_4.frequency = 130.81; test_4.dutyCycle = 0.5;
//I need to set the pin, but couldn't figure out how to do it in struct declaration
//Also, this
int *pinPointer_1; pinPointer_1 = &test_1.pin; *pinPointer_1 = 3;
int *pinPointer_2; pinPointer_2 = &test_2.pin; *pinPointer_2 = 4;
int *pinPointer_3; pinPointer_3 = &test_3.pin; *pinPointer_3 = 5;
int *pinPointer_4; pinPointer_4 = &test_4.pin; *pinPointer_4 = 6;
}
void loop() {
test_1.updateSound();
test_2.updateSound();
test_3.updateSound();
test_4.updateSound();
}
Effectively my script SHOULD work fine, but the arduino IDE is complaining:
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB
C:\Users\aj200\Documents\GitHub\My-Projects\My-Projects\Active Projects\Sound_PWM_Help\Sound_PWM_Help.ino: In member function 'updateSound':
Sound_PWM_Help:19:7: error: call to 'NonConstantUsed' declared with attribute error:
digitalWriteFast(pin,false);
^
Sound_PWM_Help:24:7: error: call to 'NonConstantUsed' declared with attribute error:
digitalWriteFast(pin,true);
^
lto-wrapper.exe: fatal error: C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-gcc returned 1 exit status
compilation terminated.
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: error: lto-wrapper failed
collect2.exe: error: ld returned 1 exit status
exit status 1
call to 'NonConstantUsed' declared with attribute error:
In theory, this should be complete and functional. HOWEVER, for some reason the arduino compiler is saying that the variable "pin" is not constant (digitalWriteFast(pin,state) requires constant value annoyingly). What am I missing here?
Thanking you in advance,
Andrey
Why don't you create a struct constructor to assign the pins. Then a setup method could define them as pins using pinModeFast()
This is my take on this. Compiled successfully for Arduino Uno and Leonardo but untested for now. To me, it looks cleaner and easier to follow and grow
#include <digitalWriteFast.h>
struct AudioHandler {
//Alter these as you require
int _pin;
float frequency;
float dutyCycle;
AudioHandler(int pin){
_pin = pin;
}
//These are internal variables that you shouldn't touch
unsigned long prevMicros = 0;
bool onHalf = true; //This just asks which half of the wave the sound is on
//This just checks the time and asks if it should switch to the other half of the wave
void updateSound() {
if ((micros() - prevMicros > (1000000 / frequency) * dutyCycle) && (onHalf)) {
prevMicros = micros();
onHalf = false;
digitalWriteFast(_pin, LOW); // Changed from false
} else if ((micros() - prevMicros > (1000000 / frequency) * (1 - dutyCycle)) && (!onHalf)) {
prevMicros = micros();
onHalf = true;
digitalWriteFast(_pin, HIGH); // Changed from true
}
}
void setup(int freq, int duty){
pinModeFast(_pin, OUTPUT);
frequency = freq;
dutyCycle = duty;
}
};
// Instantiate your audio handlers passing the pin number according to the constructor
AudioHandler test_1 = AudioHandler(3);
AudioHandler test_2 = AudioHandler(4);
AudioHandler test_3 = AudioHandler(5);
AudioHandler test_4 = AudioHandler(6);
void setup() {
// Set them up passing frequency and duty cycle
test_1.setup(65.41,0.5);
test_2.setup(82.41, 0.5);
test_3.setup(98.00, 0.5);
test_4.setup(130.81,0.5);
}
void loop() {
test_1.updateSound();
test_2.updateSound();
test_3.updateSound();
test_4.updateSound();
}
Related
I'm trying to use a teensy 4.1 as an interface between an encoder and ROS thanks to micro-ros (arduino version).
I would like to publish position of a wheel to the /jointState topic with the teensy but there is no example on the micro-ros arduino Github repo.
I've tried to inspect the sensormsgs/msg/jointState message struct but everything is a bit fuzzy and I don't understand how to make it works. I can't understand what is rosidl_runtime_c__double__Sequence type.
I've tried several things but I always get an error about operand types
no match for 'operator=' (operand types are 'rosidl_runtime_c__String' and 'const char [18]')
msg.name.data[0] = "drivewhl_1g_joint";
Here is my arduino code
#include <micro_ros_arduino.h>
#include <stdio.h>
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <sensor_msgs/msg/joint_state.h>
rcl_publisher_t publisher;
sensor_msgs__msg__JointState msg;
rclc_executor_t executor;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;
rcl_timer_t timer;
#define LED_PIN 13
#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){error_loop();}}
#define RCSOFTCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){}}
void error_loop(){
while(1){
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
delay(100);
}
}
void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
RCLC_UNUSED(last_call_time);
if (timer != NULL) {
RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
//
//Do not work
//msg.name=["drivewhl_1g_joint","drivewhl_1d_joint","drivewhl_2g_joint","drivewhl_2d_joint"];
//msg.position=["1.3","0.2", "0","0"];
msg.name.size = 1;
msg.name.data[0] = "drivewhl_1g_joint";
msg.position.size = 1;
msg.position.data[0] = 1.85;
}
}
void setup() {
set_microros_transports();
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
delay(2000);
allocator = rcl_get_default_allocator();
//create init_options
RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));
// create node
RCCHECK(rclc_node_init_default(&node, "micro_ros_arduino_node", "", &support));
// create publisher
RCCHECK(rclc_publisher_init_default(
&publisher,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, JointState),
"JointState"));
// create timer,
const unsigned int timer_timeout = 1000;
RCCHECK(rclc_timer_init_default(
&timer,
&support,
RCL_MS_TO_NS(timer_timeout),
timer_callback));
// create executor
RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));
RCCHECK(rclc_executor_add_timer(&executor, &timer));
}
void loop() {
delay(100);
RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));
}
I'm a beginner with Ros and C, it may be a very dumb question but I don't know how to solve it. Thanks for your help !
rosidl_runtime_c__String__Sequence is a structure used to old string data that is to be transmitted. Specifically it is a sequence of rosidl_runtime_c__String data. You're running into an error because rosidl_runtime_c__String is also a struct itself with no custom operators defined. Thus, your assignment fails since the types are not directly convertible. What you need to do instead is use the rosidl_runtime_c__String.data field. You can see slightly more info here
void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
RCLC_UNUSED(last_call_time);
if (timer != NULL) {
//msg.name=["drivewhl_1g_joint","drivewhl_1d_joint","drivewhl_2g_joint","drivewhl_2d_joint"];
//msg.position=["1.3","0.2", "0","0"];
msg.name.size = 1;
msg.name.data[0].data = "drivewhl_1g_joint";
msg.name.data[0].size = 17; //Size in bytes excluding null terminator
msg.position.size = 1;
msg.position.data[0] = 1.85;
RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
}
}
I also spent quite some time trying to get publishing JointState message from my esp32 running microros, and also couldn't find working example. Finally, i was successful, maybe it will help someone.
In simple words:
.capacity contains max number of elements
.size contains actual number of elements (strlen in case of string)
.data should be allocated as using malloc as .capacity * sizeof()
each string within sequence should be allocated separately
This is my code that allocates memory for 12 joints, named j0-j11. Good luck!
...
// Declarations
rcl_publisher_t pub_joint;
sensor_msgs__msg__JointState joint_state_msg;
...
// Create publisher
RCCHECK(rclc_publisher_init_default(&pub_joint, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, JointState),
"/hexapod/joint_state"));
//Allocate memory
joint_state_msg.name.capacity = 12;
joint_state_msg.name.size = 12;
joint_state_msg.name.data = (std_msgs__msg__String*) malloc(joint_state_msg.name.capacity*sizeof(std_msgs__msg__String));
for(int i=0;i<12;i++) {
joint_state_msg.name.data[i].data = malloc(5);
joint_state_msg.name.data[i].capacity = 5;
sprintf(joint_state_msg.name.data[i].data,"j%d",i);
joint_state_msg.name.data[i].size = strlen(joint_state_msg.name.data[i].data);
}
joint_state_msg.position.size=12;
joint_state_msg.position.capacity=12;
joint_state_msg.position.data = malloc(joint_state_msg.position.capacity*sizeof(double));
joint_state_msg.velocity.size=12;
joint_state_msg.velocity.capacity=12;
joint_state_msg.velocity.data = malloc(joint_state_msg.velocity.capacity*sizeof(double));
joint_state_msg.effort.size=12;
joint_state_msg.effort.capacity=12;
joint_state_msg.effort.data = malloc(joint_state_msg.effort.capacity*sizeof(double));
for(int i=0;i<12;i++) {
joint_state_msg.position.data[i]=0.0;
joint_state_msg.velocity.data[i]=0.0;
joint_state_msg.effort.data[i]=0.0;
}
....
//Publish
RCSOFTCHECK(rcl_publish(&pub_joint, &joint_state_msg, NULL));
I've created the following network topology in Mininet to run an algorithm I've implemented using the Linux kernel eXpress Data Path.
The objective is to sample packets on the incoming link s1-eth1 on Switch 1 using XDP and store metadata in a shared BPF map. The execution is successful when run on multiple VMs (instead of using Mininet to create an emulation).
However, when using XDP on Mininet (to listen on the emulated network interface), packets aren't recorded.
To further diagnose the cause, I ran Wireshark to listen on the s1-eth1 interface, which does record packets hitting the interface, but for some reason these same packets aren't being registered through the XDP pipeline.
#define KBUILD_MODNAME "foo"
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
//BPF_TABLE("percpu_array", uint32_t, long, dropcnt, 256);
BPF_HASH(proto_map, uint32_t, uint32_t, 256);
//Packet Counter to keep track of number of packets flowing through XDP
BPF_ARRAY(pkt_count, uint64_t, 1);
//Map to keep track of the current EPOCH SIZE
BPF_ARRAY(epoch_size_map, uint64_t, 1);
static inline int parse_ipv4(void *data, u64 nh_off, void *data_end,
__be32 *src, __be32 *dest)
{
struct iphdr *iph = data + nh_off;
if (iph + 1 > data_end)
return 0;
*src = iph->saddr;
*dest = iph->daddr;
return iph->protocol;
}
static inline int bitXor(int* x, int* y)
{
int a = *x & *y;
int b = ~*x & ~*y;
int z = ~a & ~b;
return z;
}
int xdp_dsa(struct CTXTYPE *ctx) {
void* data_end = (void*)(long)ctx->data_end;
void* data = (void*)(long)ctx->data;
struct ethhdr *eth = data;
// drop packets
int rc = RETURNCODE; // let pass XDP_PASS or redirect to tx via XDP_TX
uint32_t *value;
uint32_t *counter_value;
uint32_t *epoch_size;
uint16_t h_proto;
uint64_t nh_off = 0;
uint32_t ipproto;
uint64_t magic_value = 12345678;
uint32_t packet = 0;
__be32 src_ip = 0, dest_ip = 0;
nh_off = sizeof(*eth);
if (data + nh_off > data_end)
pkt_count.increment(packet);
return rc;
h_proto = eth->h_proto;
if (h_proto == htons(ETH_P_IP))
ipproto = parse_ipv4(data, nh_off, data_end, &src_ip, &dest_ip);
/*
else if (h_proto == htons(ETH_P_IPV6))
index = parse_ipv6(data, nh_off, data_end);
*/
else
ipproto = 0; //i.e. unknown protocol
/*XOR the srcIP, destIP, and ipproto to encode, then hash*/
int xor_src_dest = bitXor(&src_ip, &dest_ip);
int xor_srcdst_ipproto = bitXor(&xor_src_dest, &ipproto);
uint32_t zero = 0;
//Predecided initial epoch size
uint32_t init_epoch_size = 10;
//Variable to store the current epoch size (to check end of epoch)
uint32_t cur_epoch_size;
//Lookup epoch size from shared map (to check whether intialized else read)
epoch_size = epoch_size_map.lookup(&zero);
// Start condition (epoch size map is initialized with zero), then set to initial epoch size
// Else read the current epoch size into a variable
if(epoch_size)
{
if(*epoch_size == 0)
{
*epoch_size = init_epoch_size;
}
else
{
cur_epoch_size = *epoch_size;
}
}
counter_value = pkt_count.lookup(&packet);
if (counter_value)
{
if (*counter_value < cur_epoch_size)
{
value = proto_map.lookup_or_init(&xor_srcdst_ipproto, &zero);
if (value)
{
pkt_count.increment(packet);
*value += 1;
}
}
else if (*counter_value == cur_epoch_size)
{
pkt_count.update(&packet, &magic_value);
}
else if(*counter_value == magic_value)
{
return rc;
}
}
return rc;
}
Any ideas?
I was trying to write items to the EEPROM and later read them out. I was finding the reading back I was not getting the same as I put in at times. I narrow down to an example I can show you. Below I read into variables 2 address.
const int start_add_type = (EEPROM.length() - 10);
const int start_add_id = (EEPROM.length() - 4);
I then look at the value (via RS232)
Serial.begin(9600);
Serial.println(start_add_type);
Serial.println(start_add_id);
of them at the start of the setup() and see I get
1014
1020
I then look again at the end
Serial.println(start_add_type);
Serial.println(start_add_id);
and I get
1014
818
I cannot see why this should change. I did try calling them const e.g. const
const int start_add_type = (EEPROM.length() - 10);
const int start_add_id = (EEPROM.length() - 4);
but this gave the same result. So here I sit very puzzled at what I must have missed. Anyone got any idea?
#include "EEPROM.h"
int start_add_type = (EEPROM.length() - 10);
int start_add_id = (EEPROM.length() - 4);
char ID[7] = "ENCPG2";
char Stored_ID[5];
char Input[10];
//String Type;
void setup()
{
Serial.begin(9600);
Serial.println(start_add_type);
Serial.println(start_add_id);
// start_add = (EEPROM.length() - 10); // use this method to be PCB independent.
for (int i = 0; i < 6; i++)
{
Stored_ID[i] = EEPROM.read(start_add_type + i); // Read the ID into the EEPROM.
}
if (Stored_ID != ID) // Check if the one we have got is the same as the one in this code ID[7]
{
for (int i = 0; i < 6; i++)
{
EEPROM.write(start_add_type + i, ID[i]); // Write the ID into the EEPROM.
}
}
Serial.println(start_add_type);
Serial.println(start_add_id);
}
void loop()
{
}
You are overwriting your memory in this loop:
for (int i = 0; i < 6; i++)
{
Stored_ID[i] = EEPROM.read(start_add_type + i);
}
Stored_ID array is 5 bytes long, so writing to Stored_ID[5] will rewrite also the start_add_id variable, thus the weird value 818, which equals to 0x0332 HEX and 0x32 is the '2' character of your ID
For fixing this issue, declare Stored_ID in this way:
char Stored_ID[6];
if (Stored_ID != ID)
This is nonsense: You compare two different addresses, which are never equal. If you want to compare the content, you should do it in a loop. (e.g. directly when reading the EEPROM value into Stored_ID[i] )
Alternatively, Stored_ID could be a 0-terminated text as well and you might use
if (strcmp(Stored_ID, ID) != 0)
QElapsedTimer timer;
timer.start();
slowOperation1();
qDebug() << "The slow operation took" << timer.elapsed() << "milliseconds";
http://doc.qt.io/qt-5/qelapsedtimer.html#invalidate
After qDebug() I would want to stop this timer. I can't see a stop function there, nor a single shot property.
What's the way out?
You can't stop QElapsedTimer, because there is no timer. When you call method start(), QElapsedTimer saves the current time.
From qelapsedtimer_generic.cpp
void QElapsedTimer::start() Q_DECL_NOTHROW
{
restart();
}
qint64 QElapsedTimer::restart() Q_DECL_NOTHROW
{
qint64 old = t1;
t1 = QDateTime::currentMSecsSinceEpoch();
t2 = 0;
return t1 - old;
}
When elapsed, it gets current time again, and calculate difference.
qint64 QElapsedTimer::elapsed() const Q_DECL_NOTHROW
{
return QDateTime::currentMSecsSinceEpoch() - t1;
}
P.S. Specific realization is platform dependent: Windows, Unix, Mac
QElapsedTimer will use the platform's monotonic reference clock in all platforms that support it. This has the added benefit that QElapsedTimer is immune to time adjustments, such as the user correcting the time. Also unlike QTime, QElapsedTimer is immune to changes in the timezone settings, such as daylight-saving periods.
https://doc.qt.io/qt-5/qelapsedtimer.html#details
I needed an elapsed timer that wouldn't count the paused time, so here's what I came up with:
ElapsedTimer.hpp:
#pragma once
#include <time.h>
#include <cstdio>
#include <cstdint>
#include <cstring>
#include <errno.h>
namespace your_namespace {
class ElapsedTimer {
public:
ElapsedTimer();
~ElapsedTimer();
void Continue();
void Pause();
int64_t elapsed_ms();
private:
struct timespec start_ = {};
int64_t worked_time_ = 0;
/// CLOCK_MONOTONIC_COARSE is faster but less precise
/// CLOCK_MONOTONIC_RAW is slower but more precise
const clockid_t clock_type_ = CLOCK_MONOTONIC_RAW;
};
}
ElapsedTimer.cpp:
#include "ElapsedTimer.hpp"
namespace your_namespace {
ElapsedTimer::ElapsedTimer() {}
ElapsedTimer::~ElapsedTimer() {}
inline int64_t GetDiffMs(const timespec &end, const timespec &start) {
return (end.tv_sec - start.tv_sec) * 1000L + (end.tv_nsec - start.tv_nsec) / 1000000L;
}
void ElapsedTimer::Continue()
{
int status = clock_gettime(clock_type_, &start_);
if (status != 0)
printf("%s", strerror(errno));
}
int64_t ElapsedTimer::elapsed_ms()
{
const bool paused = (start_.tv_sec == 0 && start_.tv_nsec == 0);
if (paused)
return worked_time_;
struct timespec now;
int status = clock_gettime(clock_type_, &now);
if (status != 0)
printf("%s", strerror(errno));
const int64_t extra = GetDiffMs(now, start_);
return worked_time_ + extra;
}
void ElapsedTimer::Pause() {
struct timespec now;
int status = clock_gettime(clock_type_, &now);
if (status != 0)
printf("%s", strerror(errno));
worked_time_ += GetDiffMs(now, start_);
start_ = {};
}
}
To be used as:
my_namespace::ElapsedTimer timer;
timer.Continue(); // starts recording the amount of time
timer.Pause();// stops recording time
///do something else
timer.Continue();// resumes recording time
/// and at any time call this to find out how many
/// ms passed excluding the paused time:
int64_t passed_ms = timer.elapsed_ms();
My chip just stop doing anything. sometimes it prints good results, sometimes its not, i just cant understand whats wrong with this code( and generally any time you using Strings it happens )
void ParseGetRequest(char* data)
{
String parseGET=data;
String from="GET /";
String to="HTTP";
int ind1 = parseGET.indexOf(from);
int ind2 = parseGET.indexOf(to);
parseGET=parseGET.substring(ind1+from.length(), ind2-1);
strcpy(data, parseGET.c_str () );
}
And calling it with :
void readWifDataAsSever(char* reqData)
{
uint8_t buffer[128] = {0};
uint8_t mux_id;
uint32_t len = wifi.recv(&mux_id, buffer, sizeof(buffer), 100);
char serverData[100]={0};
if (len > 0)
{
for(uint32_t i = 0; i < len; i++)
serverData[i]=(char)buffer[i];
ParseGetRequest( serverData ); ///****** the call
Serial.println(serverData); // prints only part of the values
//here the chip just freeze and stop the main loop
NULL termination !!!!
serverData[len ] = '\0';