Skip to content

Commit

Permalink
Merge pull request #389 from micro-manager/ArduinoCounter
Browse files Browse the repository at this point in the history
Arduino counter, adds option to invert output
  • Loading branch information
nicost authored Oct 10, 2023
2 parents 0f3d7f6 + 2599940 commit 1d41fde
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 62 deletions.
71 changes: 67 additions & 4 deletions DeviceAdapters/ArduinoCounter/ArduinoCounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// COPYRIGHT: Altos Labs, 2023, based on code copyright UCSF 2008
// LICENSE: LGPL
//
// AUTHOR: Nico Stuurman, [email protected], 7/13/2023
// AUTHOR: Nico Stuurman, [email protected], 7/13/2023, 10/10/2023
//

#include "ArduinoCounter.h"
Expand All @@ -25,10 +25,13 @@ const char* g_DeviceNameArduinoCounterCamera = "ArduinoCounterCamera";


// Global info about the state of the Arduino.
const double g_Min_MMVersion = 1.0;
const double g_Max_MMVersion = 1.1;
const double g_Min_MMVersion = 2.0;
const double g_Max_MMVersion = 2.0;
const char* g_versionProp = "Version";
const char* g_Undefined = "Undefined";
const char* g_Logic = "Output Logic";
const char* g_Direct = "Direct";
const char* g_Invert = "Invert";



Expand Down Expand Up @@ -64,7 +67,8 @@ MODULE_API void DeleteDevice(MM::Device* pDevice)
ArduinoCounterCamera::ArduinoCounterCamera() :
imageBuffer_(0),
nrCamerasInUse_(0),
initialized_(false)
initialized_(false),
invert_(false)
{
InitializeDefaultErrorMessages();

Expand Down Expand Up @@ -167,6 +171,11 @@ int ArduinoCounterCamera::Initialize()
sversion << version_;
CreateProperty(g_versionProp, sversion.str().c_str(), MM::Float, true, pAct);

pAct = new CPropertyAction(this, &ArduinoCounterCamera::OnLogic);
CreateProperty(g_Logic, g_Direct, MM::String, false, pAct);
AddAllowedValue(g_Logic, g_Direct);
AddAllowedValue(g_Logic, g_Invert);


initialized_ = true;

Expand Down Expand Up @@ -745,6 +754,60 @@ int ArduinoCounterCamera::OnPort(MM::PropertyBase* pProp, MM::ActionType pAct)
return DEVICE_OK;
}

int ArduinoCounterCamera::OnLogic(MM::PropertyBase* pProp, MM::ActionType pAct)
{
int ret = DEVICE_OK;
unsigned char command[2];
command[0] = 'p';
std::string answer;
if (pAct == MM::BeforeGet)
{
command[1] = '?';
ret = WriteToComPort(port_.c_str(), (const unsigned char*)command, 2);
if (ret != DEVICE_OK)
return ret;
ret = GetSerialAnswer(port_.c_str(), "\r\n", answer);
if (ret != DEVICE_OK)
return ret;
if (answer == g_Invert)
invert_ = true;
else if (answer == g_Direct)
invert_ = false;
else
return DEVICE_SERIAL_INVALID_RESPONSE;
}
else if (pAct == MM::AfterSet)
{
std::string cmd;
pProp->Get(cmd);
if (cmd == g_Invert) {
command[1] = 'i';
ret = WriteToComPort(port_.c_str(), (const unsigned char*)command, 2);
if (ret != DEVICE_OK)
return ret;
ret = GetSerialAnswer(port_.c_str(), "\r\n", answer);
if (ret != DEVICE_OK)
return ret;
if (answer != g_Invert)
return DEVICE_SERIAL_INVALID_RESPONSE;
invert_ = true;
}
else if (cmd == g_Direct) {
command[1] = 'd';
ret = WriteToComPort(port_.c_str(), (const unsigned char*)command, 2);
if (ret != DEVICE_OK)
return ret;
ret = GetSerialAnswer(port_.c_str(), "\r\n", answer);
if (ret != DEVICE_OK)
return ret;
if (answer != g_Direct)
return DEVICE_SERIAL_INVALID_RESPONSE;
invert_ = false;
}
}
return DEVICE_OK;
}

int ArduinoCounterCamera::OnVersion(MM::PropertyBase* pProp, MM::ActionType pAct)
{
if (pAct == MM::BeforeGet)
Expand Down
1 change: 1 addition & 0 deletions DeviceAdapters/ArduinoCounter/ArduinoCounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class ArduinoCounterCamera : public CCameraBase<ArduinoCounterCamera>
std::string port_;
double version_;
bool portAvailable_;
bool invert_;
};


Expand Down
172 changes: 114 additions & 58 deletions DeviceAdapters/ArduinoCounter/ArduinoCounter/ArduinoCounter.ino
Original file line number Diff line number Diff line change
@@ -1,89 +1,145 @@
unsigned int version_ = 1;
// Arduino firmware that counts input pulses, relays these to
// the output, but stops doing so after a specified
// amount of pulses has been received.
// Since version 2, also can invert the output.
// Communicates through serial, commands:
// gnnn - starts pulse counting. nnn should be an
// integer number (of any size)
// s - Stops counting, and reverts to transducing
// all input to the output
// i - Info: returns identification string
// pn - Sets/Reads the flag inverting the input polarity
// n=i Invert the input to the output
// n=d Do not invert the input to the output
// n=? report output polarity

// pin on which to receive the trigger (2 and 3 can be used with interrupts, although this code does not use interrupts)
const int inPin = 2;


const int outPin = 8;

const unsigned long timeOut = 1000;
unsigned int version_ = 2;

unsigned int counter = 0;
unsigned int limit;
boolean counting = false;
boolean inputWas;
// pin on which to receive the trigger (2 and 3 can be used with interrupts, although this code does not use interrupts)
const int inPin = 2;


const int outPin = 8;

const unsigned long timeOut = 1000;

unsigned int counter = 0;
unsigned int limit;
boolean counting = false;
boolean inputWas;
boolean invert = false;

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.begin(115200);


pinMode(inPin, INPUT);
pinMode(outPin, OUTPUT);
pinMode(inPin, INPUT);
pinMode(outPin, OUTPUT);

inputWas = digitalRead(inPin);

inputWas = digitalRead(inPin);
}

void loop() {
while(true){
// put your main code here, to run repeatedly:

if (Serial.available() > 0) {
int inByte = Serial.read();
switch (inByte) {

// go (i.e. start) 'g' followed by max number of TTLs to pass
case 103:
if (waitForSerial(timeOut)) {
limit = Serial.parseInt();
Serial.write("Starting with ");
Serial.println(limit, DEC);
while (true) {
// put your main code here, to run repeatedly:

if (Serial.available() > 0) {
int inByte = Serial.read();
switch (inByte) {

// go (i.e. start) 'g' followed by max number of TTLs to pass
case 103:
if (waitForSerial(timeOut)) {
limit = Serial.parseInt();
Serial.write("Starting with ");
Serial.println(limit, DEC);
// set limit here
counting = true;
counter = 0;
inputWas = digitalRead(inPin);
break;
}
counting = true;
counter = 0;
inputWas = digitalRead(inPin);
break;
}

// stop 's'; i.e. operate in passthrough mode
case 115:
counting = false;
Serial.println("Stopping");
Serial.println("Stopping");
break;

// get info 'i'; what version are you?
case 105:
Serial.println("ArduinoCounter version 1.0");
}


}
Serial.println("ArduinoCounter version 2.0");
break;

// Sets/gets output polarity
case 112:
if (waitForSerial(timeOut)) {
int command = Serial.read();
switch (command) {
case 105: // "i"
invert = true;
Serial.println("Invert");
break;

case 100: // "d"
invert = false;
Serial.println("Direct");
break;

case 63: // "?"
if (invert) {
Serial.println("Invert");
} else {
Serial.println("Direct");
}
break;
}
}
}
}


if (counting) {
if (inputWas && !(PIND & B00000100)) {
counter++;
inputWas = LOW;
if (counter <= limit) {
if (counting) {
if (invert) {
if (inputWas && !(PIND & B00000100)) {
counter++;
inputWas = LOW;
PORTB = 1;
} else if (!inputWas && (PIND & B00000100)) {
counter++;
inputWas = HIGH;
if (counter <= limit) {
PORTB = 0;
}
}
} else { // do not invert output
if (inputWas && !(PIND & B00000100)) {
counter++;
inputWas = LOW;
if (counter <= limit) {
PORTB = 0;
}
} else if (!inputWas && (PIND & B00000100)) {
}
} else if (!inputWas && (PIND & B00000100)) {
inputWas = HIGH;
PORTB = 1;
}
}
} else {
PORTB = (PIND & B00000100) >> 2;
}
} else { // not counting
if (invert) {
PORTB = !(PIND & B00000100);
} else {
PORTB = (PIND & B00000100) >> 2;
}
}
}
}

bool waitForSerial(unsigned long timeOut)
{
unsigned long startTime = millis();
while (Serial.available() == 0 && (millis() - startTime < timeOut) ) {}
if (Serial.available() > 0)
return true;
return false;
}
bool waitForSerial(unsigned long timeOut) {
unsigned long startTime = millis();
while (Serial.available() == 0 && (millis() - startTime < timeOut)) {}
if (Serial.available() > 0)
return true;
return false;
}

0 comments on commit 1d41fde

Please sign in to comment.