Related
Currently I am having issues with a program running a freertos program. The purpose of the program is to control a stepper motor as well as an led. Implementing the motor control without microstepping does not have any issues as the two tasks take no parameters and call no functions.
However, when I introduce microstepping which requires two nested functions to be called by the move_routine task, the program will not do anything (no led flashing, no motor turning) when it did before. Does anyone have any solutions for this or any reasons on why this shouldn't work? From what I can see it should be fine to call a function from a freertos task.
#include <Arduino.h>
#include <Stepper.h>
/*================PIN DEFINITIONS================*/
#define LEDC_CHANNEL_0 0
#define LEDC_CHANNEL_1 1
#define LEDC_CHANNEL_2 2
#define LEDC_CHANNEL_3 3
const int A1A = 14;
const int A1B = 27;
const int B1A = 26;
const int B2A = 25;
const int ledPin = 33;
/*================VARIABLE DEFINITIONS================*/
int stepnumber = 0;
int Pa; int Pb;
const int stepsPerRev = 200;
Stepper myStepper(stepsPerRev, 14,27,26,25);
/*================Function Definitions================*/
//Analogwrite using LEDC capabilities
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
//calculation of duty cycle
uint32_t duty = (4095/valueMax)*min(value, valueMax);
ledcWrite(channel,duty);
}
void move(int stepnumber, int MAXpower, int wait) {
Pa = (sin(stepnumber*0.098174)*MAXpower);
Pb = (cos(stepnumber*0.098174)*MAXpower);
if (Pa>0)
{
ledcAnalogWrite(LEDC_CHANNEL_0,Pa);
ledcAnalogWrite(LEDC_CHANNEL_1,0);
}
else
{
ledcAnalogWrite(LEDC_CHANNEL_0,0);
ledcAnalogWrite(LEDC_CHANNEL_1,abs(Pa));
}
if (Pb>0)
{
ledcAnalogWrite(LEDC_CHANNEL_2,Pb);
ledcAnalogWrite(LEDC_CHANNEL_3,0);
}
else
{
ledcAnalogWrite(LEDC_CHANNEL_2,0);
ledcAnalogWrite(LEDC_CHANNEL_3,abs(Pb));
}
}
void move_routine(void *parameters) {
while(1) {
for (int i=0; i<3199; i++)
{
stepnumber++;
move(stepnumber,255,250);
}
vTaskDelay(3000/portTICK_PERIOD_MS);
for (int i=0; i<1599; i++)
{
stepnumber--;
move(stepnumber,255,1000);
}
vTaskDelay(3000/portTICK_PERIOD_MS);
}
}
void led_task(void * parameters){
while(1){
digitalWrite(ledPin, HIGH);
vTaskDelay(500/portTICK_PERIOD_MS);
digitalWrite(ledPin, LOW);
vTaskDelay(500/portTICK_PERIOD_MS);
}
}
void setup(){
myStepper.setSpeed(60);
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
xTaskCreatePinnedToCore(
move_routine,
"Move Routine",
8192,
NULL,
1,
NULL,
1
);
xTaskCreatePinnedToCore(
led_task,
"LED Task",
1024,
NULL,
1,
NULL,
1
);
}
void loop(){
}
Expected to see flashing led and motor turning but nothing witnessed
Your two tasks work as it were defined, the problem is your ledcAnalogWrite() function where you are calling ledcWrite() function with nowhere in your code initialise the LEDC with ledcSetup() and ledcAttachPin().
Read the documentation on LED Control(LEDC).
I'm currently working on a small game to learn Processing.
I want my game to stop when I press "Stop" and want my game to reset/restart when "Stop" changed to Start.
(When I click on the button, it changes Stop to Start and back to Stop etc etc. (so basically, I have 1 'button')
I'm struggling and can't find a solution on internet / stackoverflow so maybe someone can help me?
(# mousePressed's if else I need the 'stop and restart function')
float x = width/2;
float speed = 2;
boolean textHasBeenClicked = false;
int aantalRaak = 0;
int aantalMis = 0;
int positieText = 20;
void setup() {
background(0);
size(600,500);
}
void draw() {
clear();
move();
display();
smooth();
//Scoreboard bovenaan
fill(255);
textSize(20);
textAlign(LEFT);
text("Aantal geraakt: " + aantalRaak,0, positieText); text("Aantal gemist: " + aantalMis, width/2, positieText);
//button onderaan
fill(0,255,0);
rect(width/2-40, height-40, 100, 50);// draw anyway...
}
void mousePressed() {
// toggle
textHasBeenClicked = ! textHasBeenClicked;
fill(0);
if (textHasBeenClicked) {
// display text 2
textSize(30);
textAlign(CENTER);
text("Stop" , width/2,height-10);
}
else {
// display text 1
textSize(30);
textAlign(CENTER);
text("Start" , width/2,height-10);
}
}
void move() {
x = x + speed;
if (x > width) {
x = 0;
}
}
void display(){
//schietschijf
float y = height/2;
noStroke();
fill(255, 0, 0);
ellipse(x, y, 40, 40);
fill(255);
ellipse(x, y, 30, 30);
fill(255, 0, 0);
ellipse(x, y, 20, 20);
fill(255);
ellipse(x, y, 10, 10);
}
You should try to break your problem down into smaller steps and take those steps on one at a time. You're really asking two questions:
How do I show a stop button that turns into a start button?
How do I reset a sketch?
For the first question, you can create a boolean variable. Use that variable in your draw() function, and then modify that variable in the mousePressed() function.
boolean running = false;
void draw() {
fill(0);
if (running) {
background(255, 0, 0);
text("Stop", 25, 25);
} else {
background(0, 255, 0);
text("Start", 25, 25);
}
}
void mousePressed() {
running = !running;
}
Then for resetting the sketch, you can create a function that changes all of your variables back to their default values. Here's a simple example:
float circleY;
void setup() {
size(100, 500);
}
void draw() {
background(0);
circleY++;
ellipse(width/2, circleY, 20, 20);
}
void reset() {
circleY = 0;
}
void mousePressed() {
reset();
}
Try to work from small examples like this instead of your full program, and post a MCVE if you get stuck. Good luck.
You may consider implementing a while loop. I don't know what library you're using for input, so I can't tell you exactly what to do. But something along the lines of:
while(!InputReceived) {
if(CheckForMouseInput()) // Assuming CheckForMouseInput returns true if input was detected
break // Input was detected, now do stuff based on that.
else {
// Must #include <thread> and #include <chrono>
// Wait a bit...
continue; // Jump back to the top of the loop, effectively restarting it.
}
Would probably suit your needs. That is what I would do, at least. After the loop breaks, the game is effectively restarted, and you can do whatever you need to do based on that.
I am currently using a processing sketch to work through a large number of images I have in a folder. I have set an onClick command to advance to the next image in the string. It is quite time consuming and I would like to automate the action that once the sketch is completed the sketch would repeat it's self selecting the next image from the string. The onClick command also save the image the export folder but each time saves with the same file name, I've tried to set up sequential numbering but it hasn't worked so far. Any help would be greatly appreciated.
String[] imgNames = {"1.jpg", "2.jpg", "3.jpg"};
PImage img;
int imgIndex = 0;
void nextImage() {
background(255);
frameRate(10000);
loop();
frameCount = 0;
img = loadImage(imgNames[imgIndex]);
img.loadPixels();
imgIndex += 1;
if (imgIndex >= imgNames.length) {
imgIndex = 0;
}
}
void paintStroke(float strokeLength, color strokeColor, int strokeThickness) {
float stepLength = strokeLength/4.0;
// Determines if the stroke is curved. A straight line is 0.
float tangent1 = 0;
float tangent2 = 0;
float odds = random(1.0);
if (odds < 0.7) {
tangent1 = random(-strokeLength, strokeLength);
tangent2 = random(-strokeLength, strokeLength);
}
// Draw a big stroke
noFill();
stroke(strokeColor);
strokeWeight(strokeThickness);
curve(tangent1, -stepLength*2, 0, -stepLength, 0, stepLength, tangent2, stepLength*2);
int z = 1;
// Draw stroke's details
for (int num = strokeThickness; num > 0; num --) {
float offset = random(-50, 25);
color newColor = color(red(strokeColor)+offset, green(strokeColor)+offset, blue(strokeColor)+offset, random(100, 255));
stroke(newColor);
strokeWeight((int)random(0, 3));
curve(tangent1, -stepLength*2, z-strokeThickness/2, -stepLength*random(0.9, 1.1), z-strokeThickness/2, stepLength*random(0.9, 1.1), tangent2, stepLength*2);
z += 1;
}
}
void setup() {
size(1600, 700);
nextImage();
}
void draw() {
translate(width/2, height/2);
int index = 0;
for (int y = 0; y < img.height; y+=1) {
for (int x = 0; x < img.width; x+=1) {
int odds = (int)random(20000);
if (odds < 1) {
color pixelColor = img.pixels[index];
pixelColor = color(red(pixelColor), green(pixelColor), blue(pixelColor), 100);
pushMatrix();
translate(x-img.width/2, y-img.height/2);
rotate(radians(random(-90, 90)));
// Paint by layers from rough strokes to finer details
if (frameCount < 20) {
// Big rough strokes
paintStroke(random(150, 250), pixelColor, (int)random(20, 40));
} else if (frameCount < 1000) {
// Thick strokes
paintStroke(random(75, 125), pixelColor, (int)random(8, 12));
} else if (frameCount < 1500) {
// Small strokes
paintStroke(random(20, 30), pixelColor, (int)random(1, 4));
} else if (frameCount < 10000) {
// Big dots
paintStroke(random(5, 10), pixelColor, (int)random(5, 8));
} else if (frameCount < 10000) {
// Small dots
paintStroke(random(1, 2), pixelColor, (int)random(1, 3));
}
popMatrix();
}
index += 1;
}
}
if (frameCount > 10000) {
noLoop();
}
// if(key == 's'){
// println("Saving...");
// saveFrame("screen-####.jpg");
// println("Done saving.");
// }
}
void mousePressed() {
save("001.tif");
nextImage();
}
Can't you just call the nextImage() function from inside this if statement?
if (frameCount > 10000) {
noLoop();
}
Would be:
if (frameCount > 10000) {
nextImage();
}
As for using different filenames, just use an int that you increment whenever you save the file, and use that value in the save() function. Or you could use the frameCount variable:
save("img" + frameCount + ".tif");
If you have follow-up questions, please post a MCVE instead of your whole project. Try to isolate one problem at a time in a small example program that only does that one thing. Good luck.
i use an Arduino Mega compatible board (SainSmart Mega 2560 R3 ATmega2560-16AU) which has a rtc module attached (v1.1 ds1307rtc) and working on it with the attached code. I have used the TimeAlarms library (downloaded it from http://www.pjrc.com/teensy/td_libs_TimeAlarms.html) to have an alarm every hour. The alarms should occur at different minutes every hour, but for testing i have set them all to the 12th minute.
This code is waiting for a correct time, which i can set via usb, serial interface. The code is working fine most of the times. But sometimes the alarm is not activated and my leds are not flashing. I don't know why and when this happens, i didn't any changes between the working flashing and not working. Also i can't see any hours where it doesn't working correct, afaik it works correct, but fails sometimes. If it failes, it looks like all hours after the failing hour are also failing and no alarm is triggered.
I know about the restriction of 6 alarms in TimeAlarms.h and set the variable dtNBR_ALARMS in this file to 25.
As you can see i have implemented a printTime function which print out the rtc and the system time and always both are correct.
Has anyone an idea what i am doing wrong or why it fails sometimes?
#include <Time.h>
#include <TimeAlarms.h>
#include <Wire.h>
#include <DS1307RTC.h>
tmElements_t tm;
int pwm_2 = 2;
int pwm_3 = 3;
int pwm_4 = 4;
int pwm_5 = 5;
int pwm_6 = 6;
int pwm_7 = 7;
int pwm_8 = 8;
int pwm_9 = 9;
int pwm_10 = 10;
int pwm_11 = 11;
int pwm_12 = 12;
int pwm_13 = 13;
//delay in the for loops
int dly = 120;
// the setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
while (!Serial) ; // wait for serial
setSyncProvider(RTC.get); // the function to get the time from the RTC
RTC.read(tm);
setTime(tm.Hour,tm.Minute,tm.Second,tm.Day,tm.Month,tm.Year);
printTime();
//wait for time input via serial, time must be set at every system boot
while(tmYearToCalendar(tm.Year) < 2014) {
Serial.println("wait in time loop, you have to set a time, current time is not correct:");
printTime();
if (Serial.available()) {
time_t t = processSyncMessage();
Serial.println("wait in time loop");
if (t != 0) {
RTC.set(t); // set the RTC and the system time to the received value
setTime(t);
Serial.println("time is succesfully set to");
printTime();
break;
}
}
delay(1000);
}
Serial.println("Time is already set to:");
printTime();
//set alarms for all hours in UTC, not in CET
Alarm.alarmRepeat(0, 12, 0, shotAlarm);
Alarm.alarmRepeat(1, 12, 0, shotAlarm);
Alarm.alarmRepeat(2, 12, 0, shotAlarm);
Alarm.alarmRepeat(3, 12, 0, shotAlarm);
Alarm.alarmRepeat(4, 12, 0, shotAlarm);
Alarm.alarmRepeat(5, 12, 0, shotAlarm);
Alarm.alarmRepeat(6, 12, 0, shotAlarm);
Alarm.alarmRepeat(7, 12, 0, shotAlarm);
Alarm.alarmRepeat(8, 12, 0, shotAlarm);
Alarm.alarmRepeat(9, 12, 0, shotAlarm);
Alarm.alarmRepeat(10, 12, 0, shotAlarm);
Alarm.alarmRepeat(11, 12, 0, shotAlarm);
Alarm.alarmRepeat(12, 12, 0, shotAlarm);
Alarm.alarmRepeat(13, 12, 0, shotAlarm);
Alarm.alarmRepeat(14, 12, 0, shotAlarm);
Alarm.alarmRepeat(15, 12, 0, shotAlarm);
Alarm.alarmRepeat(16, 12, 0, shotAlarm);
Alarm.alarmRepeat(17, 12, 0, shotAlarm);
Alarm.alarmRepeat(18, 12, 0, shotAlarm);
Alarm.alarmRepeat(19, 12, 0, shotAlarm);
Alarm.alarmRepeat(20, 12, 0, shotAlarm);
Alarm.alarmRepeat(21, 12, 0, shotAlarm);
Alarm.alarmRepeat(22, 12, 0, shotAlarm);
Alarm.alarmRepeat(23, 12, 0, shotAlarm);
// declare pin 2-13 to be an output:
pinMode(pwm_2, OUTPUT); //red
pinMode(pwm_3, OUTPUT); //blue
pinMode(pwm_4, OUTPUT); //green
pinMode(pwm_5, OUTPUT); //red
pinMode(pwm_6, OUTPUT); //blue
pinMode(pwm_7, OUTPUT); //green
pinMode(pwm_8, OUTPUT); //red
pinMode(pwm_9, OUTPUT); //blue
pinMode(pwm_10, OUTPUT); //green
pinMode(pwm_11, OUTPUT); //red
pinMode(pwm_12, OUTPUT); //blue
pinMode(pwm_13, OUTPUT); //green
}
void shotAlarm() {
Serial.println("SHOTALARM");
analogWrite(pwm_2, 255);
analogWrite(pwm_5, 255);
analogWrite(pwm_8, 255);
analogWrite(pwm_11, 255);
analogWrite(pwm_3, 255);
analogWrite(pwm_4, 255);
analogWrite(pwm_6, 255);
analogWrite(pwm_7, 255);
analogWrite(pwm_9, 255);
analogWrite(pwm_10, 255);
analogWrite(pwm_12, 255);
analogWrite(pwm_13, 255);
for(int a = 0; a < 60; a = a+1) {
for (int i = 0; i < 255; i = i + 1) {
analogWrite(pwm_2, i); //red
analogWrite(pwm_5, i); //red
analogWrite(pwm_8, i); //red
analogWrite(pwm_11, i); //red
delay (5);
}
for (int i = 255; i > 0; i = i - 1) {
analogWrite(pwm_2, i); //red
analogWrite(pwm_5, i); //red
analogWrite(pwm_8, i); //red
analogWrite(pwm_11, i); //red
delay (5);
}
}
}
void loop() {
Alarm.delay(0);
Serial.println("new loop");
printTime();
analogWrite(pwm_2, 0);
analogWrite(pwm_5, 0);
analogWrite(pwm_8, 0);
analogWrite(pwm_11, 0);
analogWrite(pwm_3, 255);
analogWrite(pwm_4, 255);
analogWrite(pwm_6, 255);
analogWrite(pwm_7, 255);
analogWrite(pwm_9, 255);
analogWrite(pwm_10, 255);
analogWrite(pwm_12, 255);
analogWrite(pwm_13, 255);
for (int i = 255; i > 0; i = i - 1) {
analogWrite(pwm_4, i); //green
analogWrite(pwm_7, i); //green
analogWrite(pwm_10, i); //green
analogWrite(pwm_13, i); //green
Alarm.delay (dly);
}
for (int i = 0; i < 255; i = i + 1) {
analogWrite(pwm_2, i); //red
analogWrite(pwm_5, i); //red
analogWrite(pwm_8, i); //red
analogWrite(pwm_11, i); //red
Alarm.delay (dly);
}
for (int i = 255; i > 0; i = i - 1) {
analogWrite(pwm_3, i); //blue
analogWrite(pwm_6, i); //blue
analogWrite(pwm_9, i); //blue
analogWrite(pwm_12, i); //blue
Alarm.delay (dly);
}
for (int i = 0; i < 255; i = i + 1) {
analogWrite(pwm_4, i); //green
analogWrite(pwm_7, i); //green
analogWrite(pwm_10, i); //green
analogWrite(pwm_13, i); //green
Alarm.delay (dly);
}
for (int i = 255; i > 0; i = i - 1) {
analogWrite(pwm_2, i); //red
analogWrite(pwm_5, i); //red
analogWrite(pwm_8, i); //red
analogWrite(pwm_11, i); //red
Alarm.delay (dly);
}
for (int i = 0; i < 255; i = i + 1) {
analogWrite(pwm_3, i); //blue
analogWrite(pwm_6, i); //blue
analogWrite(pwm_9, i); //blue
analogWrite(pwm_12, i); //blue
Alarm.delay (dly);
}
Alarm.delay(0);
}
void printTime() {
if (RTC.read(tm)) {
Serial.print("Ok, RTC Time = ");
print2digits(tm.Hour);
Serial.write(':');
print2digits(tm.Minute);
Serial.write(':');
print2digits(tm.Second);
Serial.print(", Date (D/M/Y) = ");
Serial.print(tm.Day);
Serial.write('/');
Serial.print(tm.Month);
Serial.write('/');
Serial.print(tmYearToCalendar(tm.Year));
Serial.println();
}
else {
if (RTC.chipPresent()) {
Serial.println("The DS1307 is stopped. Please run the SetTime");
Serial.println("example to initialize the time and begin running.");
Serial.println();
}
else {
Serial.println("DS1307 read error! Please check the circuitry.");
Serial.println();
}
}
Serial.print("Ok, System Time = ");
print2digits(hour());
Serial.write(':');
print2digits(minute());
Serial.write(':');
print2digits(second());
Serial.print(", Date (D/M/Y) = ");
Serial.print(day());
Serial.write('/');
Serial.print(month());
Serial.write('/');
Serial.print(year());
Serial.println();
}
void print2digits(int number) {
if (number >= 0 && number < 10) {
Serial.write('0');
}
Serial.print(number);
}
/* code to process time sync messages from the serial port */
#define TIME_HEADER "T" // Header tag for serial time sync message
unsigned long processSyncMessage() {
unsigned long pctime = 0L;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
if(Serial.find(TIME_HEADER)) {
pctime = Serial.parseInt();
return pctime;
if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
pctime = 0L; // return 0 to indicate that the time is not valid
}
}
return pctime;
}
For all who read this thread later:
I found the mistake in my code. The following line was wrong:
setTime(tm.Hour,tm.Minute,tm.Second,tm.Day,tm.Month,tm.Year);
The correct version is:
setTime(tm.Hour,tm.Minute,tm.Second,tm.Day,tm.Month,tmYearToCalendar(tm.Year));
Unfortunately i forgot to convert the year value to the expected format. The code from above is working very fine with this correction. I checked the alarms for more then a week and it is working very stable.
Thanks all for their help.
One thing to mention is that in the read me of the TimerAlarm library, it says you can only define up to 6 alarms only, but that can be changed inside the library by dtNBR_ALARMS field. The number ofcourse is restricted by ram but you can easily add that since the Arduino mega has a significantly large SRAM. So this might be worth looking at if you experience further problems with the alarms.
I am trying to create 100 frames where the numbers 0-100 are "printed" in the center of every frame. If I try the code below I get the error "It looks like you're mixing "active" and "static" modes".
size(1440,900);
font = loadFont("Arial-Black-96.vlw");
textFont(font,96);
int x = 0;
void draw() {
background(204);
y=0;
if (x < 100) {
text(y, 10, 50);
x = x + 1;
y=y+1;
} else {
noLoop();
}
// Saves each frame as screen-0001.tif, screen-0002.tif, etc.
saveFrame();
}
You need to wrap the first 3 lines in the setup() function.
Like:
void setup(){
size(1440,900);
font = loadFont("Arial-Black-96.vlw");
textFont(font,96);
}
I answered this without running the code, there were others issues, here a version of your code:
PFont font;
int x = 0;
int size = 96;
void setup() {
size(1440, 900);
font = createFont("Arial-Black", size);
textFont(font);
}
void draw() {
background(204);
if (x <= 100) {
String number = nf(x, 2);
text(number, width/2 - textWidth(number)/2, height/2);
x++;
saveFrame();
}
else {
exit();
}
}