问题描述
我正在尝试使用两个螺线管拍摄水滴碰撞。我使用一个螺线管成功地做到了这一点。这使用了代码中的设置延迟来为相机快门、水滴和闪光灯计时。我想以相同的延迟同时触发两个螺线管,但不确定如何执行此操作。
操作顺序应该是
- 打开相机快门(相机处于灯泡模式)
- 同时从两个螺线管中滴下两滴水。
- 闪光
- 关闭相机快门
我的平台是 Atmega 2560。这是我目前拥有的代码,
int relayCam=A0; //pin to relay to trigger camera
int relayFlash=A7 ; //pin to relay to fire flash
int button1Read;
//button read delays (settling time)
int button1DT=250;
int button1Pin=8; //pin for 2 drop button read
int DelayCamOpen=100; //wait time to trigger camera
int DelayCamClose=1000; //wait time to close camera shutter
//Drop start
int DropStart=500; //time to start first drop
//Flash timing
int DelayFlashFire1=350;
int DelayFlashOff=50; //turn flash off
bool runOnce = false;
class Solenoid
{
int SolenoidPin;
long OnTime;
long OffTime;
int SolenoidState;
unsigned long prevIoUsMillis;
public:
Solenoid(int pin,long on,long off)
{
SolenoidPin = pin;
pinMode(SolenoidPin,OUTPUT);
OnTime = on;
OffTime = off;
SolenoidState = HIGH;
prevIoUsMillis = 0;
}
void update()
{
unsigned long currentMillis = millis();
if((SolenoidState == HIGH) && (currentMillis - prevIoUsMillis >= OnTime))
{
SolenoidState = HIGH;
prevIoUsMillis = currentMillis;
digitalWrite(SolenoidPin,SolenoidState);
}
else if ((SolenoidState == LOW) && (currentMillis - prevIoUsMillis >= OffTime))
{
SolenoidState = LOW;
prevIoUsMillis = currentMillis;
digitalWrite(SolenoidPin,SolenoidState);
}
}
};
Solenoid drop1(A1,55,55);
Solenoid drop2(A2,55);
void setup()
{
pinMode(relayCam,OUTPUT);
pinMode(relayFlash,OUTPUT);
pinMode(button1Pin,INPUT);
}
void loop()
{
//This part works
button1Read=digitalRead(button1Pin);
delay (button1DT);
if(button1Read==0) {
delay (DelayCamOpen); //wait time after button is pushed to start sequence
digitalWrite (relayCam,LOW); //opens the camera shutter
delay (DropStart); //wait time after shutter opens ro start first drop
//This part does not execute
if (runOnce == false)
{runOnce = true;
drop1.update();
drop2.update();
}
//This part works
delay (DelayFlashFire1); //wait time to fire flash
digitalWrite (relayFlash,LOW); //fire flash
delay (DelayFlashOff); //time to keep flash open (very short time)
digitalWrite (relayFlash,HIGH); //close flash relay
delay (DelayCamClose); //wait time to close camera shutter
digitalWrite (relayCam,HIGH); //close camera shutter
}
else if(button1Read==1)
{
digitalWrite (drop1,HIGH); //no signal to waterdrop
digitalWrite (drop2,HIGH); //no signal to waterdrop
digitalWrite (relayCam,HIGH); //no signal to camera
digitalWrite (relayFlash,HIGH); //no signal to flash
}
}
相机和闪光灯部分工作正常,但螺线管不工作。我不确定我是否正确地解决了这个问题。我确实知道延迟运行两个螺线管并没有给我想要的结果,因此尝试使用状态机方法。非常感谢任何帮助/建议。我是编写代码和 Arduino 的新手。
//Pin assignments
int relayCam=A0; //pin to relay to trigger camera
int relayFlash=A7 ; //pin to relay to fire flash
int relayWD1=A1; //pin to relay to trigger water drop 1
int button1Read;
//button read delays (settling time)
int button1DT=250;
int button1Pin=8; //pin for 2 drop button read
//drop sizes
int dropSize1=55; //time to hold relay for 1st drop
int dropSize2=45; //time to hold relay for 2nd drop
//delays betwween drops
int Delay1=45; //time between 1st and 2nd drops
//camera shutter timings
int DelayCamOpen=100; //wait time to trigger camera
int DelayCamClose=1000; //wait time to close camera shutter
//Drop start
int DropStart=500; //time to start first drop
//Flash timing
int DelayFlashFire1=350;
int DelayFlashOff=50; //turn flash off
void setup() {
pinMode(relayCam,OUTPUT);
pinMode(relayWD1,INPUT);
}
void loop() {
button1Read=digitalRead(button1Pin);
delay (button1DT);
if(button1Read==0) {
delay (DelayCamOpen); //wait time after button is pushed to start sequence
digitalWrite (relayCam,LOW); //opens the camera shutter
delay (DropStart); //wait time after shutter opens ro start first drop
digitalWrite (relayWD1,LOW); //starts first drop
delay (dropSize1); //duration of water flow
digitalWrite (relayWD1,HIGH); //stops first drop
delay (Delay1); //wait time for second drop to start
digitalWrite (relayWD1,LOW); //start of second drop
delay (dropSize2); //duration of waterflow
digitalWrite (relayWD1,HIGH); //stops second drop
delay (DelayFlashFire1); //wait time to fire flash
digitalWrite (relayFlash,HIGH); //close camera shutter
}
else if(button1Read==1)
{digitalWrite (relayWD1,HIGH); //no signal to flash
}
}
解决方法
你的 update()
方法所代表的抽象对我来说是折磨和困惑。我的建议是用两个方法 update()
和 startDrop()
替换 stopDrop()
。 startDrop()
记录一个 startTimestamp
(就像您对 currentMillis
所做的那样,但是是一个类成员变量)并打开电磁阀。 stopDrop()
比较经过的时间,如果时间不够且电磁阀保持打开,则返回 false;如果时间足够长且电磁阀关闭,则返回 true。
class Solenoid
{
...
private unsigned long startTimestamp;
void startDrop()
{
startTimestamp = millis();
digitalWrite(SolenoidPin,LOW);
}
bool stopDrop()
{
if ((millis() - startTimestamp) >= OffTime)
{
digitalWrite(SolenoidPin,HIGH);
return true;
}
return false;
}
...
}
void loop()
{
...
drop1.startDrop();
drop2.startDrop();
while (drop1.stopDrop() == false);
while (drop2.stopDrop() == false);
...
}
这只是一个草稿。您可能需要添加一些错误检查以确保例如电磁阀在 startDrop()
之前关闭或 startDrop()
在 stopDrop()
之前被调用。