使用 H 桥和 neopixel 与 Arduino UNO 一起控制直流电机
Control dc-motor using H-Bridge and neopixel together with Arduino UNO
我正在做一个项目,用 H 桥控制直流电机正向和反向旋转。并在电路开启时同时点亮一个adafruit neopixel。
我让这两个东西分开工作。现在我合并了代码,但它不能正常工作。它的工作原理就像直流电机做一个正向和反向循环然后停止。然后 neopixel 环亮起。一段时间后,当 neopixel 代码完成后,直流电机会执行相同的循环并继续此循环。
我需要帮助使此代码同时启动直流电机工作和新像素照明。
代码如下:
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
//DC motor
const int pwm = 3; //initializing pin 2 as pwm
const int in_1 = 8 ;
const int in_2 = 7 ;
//For providing logic to L298 IC to choose the direction of the DC motor
void setup()
{
pinMode(pwm,OUTPUT) ; //we have to set PWM pin as output
pinMode(in_1,OUTPUT) ; //Logic pins are also set as output
pinMode(in_2,OUTPUT) ;
//Neopixel Ring
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop()
{
//For Clock wise motion , in_1 = High , in_2 = Low
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,LOW) ;
analogWrite(pwm,255) ;
/*setting pwm of the motor to 255
we can change the speed of rotaion
by chaning pwm input but we are only
using arduino so we are using higest
value to driver the motor */
//Clockwise for 3 secs
delay(1000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(50) ;
//For Anti Clock-wise motion - IN_1 = LOW , IN_2 = HIGH
digitalWrite(in_1,LOW) ;
digitalWrite(in_2,HIGH) ;
delay(1000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(50) ;
//Neopixel Ring
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
// Send a theater pixel chase in...
theaterChase(strip.Color(127, 127, 127), 50); // White
theaterChase(strip.Color(127, 0, 0), 50); // Red
theaterChase(strip.Color(0, 0, 127), 50); // Blue
rainbow(20);
rainbowCycle(20);
theaterChaseRainbow(50);
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
基本上每次调用 delay 时,arduino 都无法执行任何其他操作。所以你需要将控制权切换到你想做的任何其他事情。
有几种方法:
计时器 - 使用计时器来更新您的两个任务之一的状态。这样做的好处是您的任务不依赖于其他任务来产生,但不会超出几个任务。
软件状态机——为每个任务创建一个状态机,并在循环中依次递增每个状态机。您需要创建一个结构来跟踪任务的状态,并且每次调用 delay 时,您都需要更新结构和 return。通常你会为每个任务创建一个 class,就像在 this Adafruit tutorial 中所做的那样。这可能需要大量工作,因此有一些库可以为您完成。
协程 - 它们使用库为您构建状态机。例如http://forum.arduino.cc/index.php?topic=256256.0
我正在做一个项目,用 H 桥控制直流电机正向和反向旋转。并在电路开启时同时点亮一个adafruit neopixel。
我让这两个东西分开工作。现在我合并了代码,但它不能正常工作。它的工作原理就像直流电机做一个正向和反向循环然后停止。然后 neopixel 环亮起。一段时间后,当 neopixel 代码完成后,直流电机会执行相同的循环并继续此循环。
我需要帮助使此代码同时启动直流电机工作和新像素照明。
代码如下:
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);
//DC motor
const int pwm = 3; //initializing pin 2 as pwm
const int in_1 = 8 ;
const int in_2 = 7 ;
//For providing logic to L298 IC to choose the direction of the DC motor
void setup()
{
pinMode(pwm,OUTPUT) ; //we have to set PWM pin as output
pinMode(in_1,OUTPUT) ; //Logic pins are also set as output
pinMode(in_2,OUTPUT) ;
//Neopixel Ring
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop()
{
//For Clock wise motion , in_1 = High , in_2 = Low
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,LOW) ;
analogWrite(pwm,255) ;
/*setting pwm of the motor to 255
we can change the speed of rotaion
by chaning pwm input but we are only
using arduino so we are using higest
value to driver the motor */
//Clockwise for 3 secs
delay(1000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(50) ;
//For Anti Clock-wise motion - IN_1 = LOW , IN_2 = HIGH
digitalWrite(in_1,LOW) ;
digitalWrite(in_2,HIGH) ;
delay(1000) ;
//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(50) ;
//Neopixel Ring
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
//colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
// Send a theater pixel chase in...
theaterChase(strip.Color(127, 127, 127), 50); // White
theaterChase(strip.Color(127, 0, 0), 50); // Red
theaterChase(strip.Color(0, 0, 127), 50); // Blue
rainbow(20);
rainbowCycle(20);
theaterChaseRainbow(50);
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
基本上每次调用 delay 时,arduino 都无法执行任何其他操作。所以你需要将控制权切换到你想做的任何其他事情。
有几种方法:
计时器 - 使用计时器来更新您的两个任务之一的状态。这样做的好处是您的任务不依赖于其他任务来产生,但不会超出几个任务。
软件状态机——为每个任务创建一个状态机,并在循环中依次递增每个状态机。您需要创建一个结构来跟踪任务的状态,并且每次调用 delay 时,您都需要更新结构和 return。通常你会为每个任务创建一个 class,就像在 this Adafruit tutorial 中所做的那样。这可能需要大量工作,因此有一些库可以为您完成。
协程 - 它们使用库为您构建状态机。例如http://forum.arduino.cc/index.php?topic=256256.0