Final
Here is the arduino code:
/*
Little Monster Scanner
======================
Written by Alan Cooper (agp.cooper@gmail.com)
This work is licensed under the
Creative Commons Attribution - Non Commercial 2.5 License.
This means you are free to copy and share the code (but not to sell it).
Also it is good karma to attribute the source of the code.
*/
#define DirX 2 // Reserved for Head 1
#define DirY 3 // Reserved for Head 2
#define DirZ 4 // Scanner
#define StepX 5 // Reserved for Head 1
#define StepY 6 // Reserved for Head 2
#define StepZ 7 // Scanner
#define Enable 8 // Enable all stepper motors (active LOW)
#define Sensor1 A4 // SE-10 PIR Scanner (active LOW)
#define Sensor2 A5 // Reserved for RCWL-0516 (active LOW)
#define N 19 // Sample array size
volatile bool scanDone=false;
volatile byte forwardScan[N];
volatile byte reverseScan[N];
volatile unsigned int magic=0;
volatile int dirFlag=0;
volatile int stepCount=1200+80; // Offset for sensor zero (+4.5 degrees)
volatile int stepTrip=2400; // +/-60 degrees (400 step motor and 1/16 mircosteps)
volatile int index=0; // Used to save data to an array
ISR(TIMER2_OVF_vect)
{
static unsigned int phase=0;
if (phase<0x8000) {
phase+=magic;
if (phase>=0x8000) {
digitalWrite(StepZ,LOW);
}
} else {
phase+=magic;
if (phase<0x8000) {
digitalWrite(StepZ,HIGH);
stepCount++;
index=(stepCount>>7); // 0 to N-1
if (dirFlag==0) {
if (digitalRead(Sensor1)==LOW) {
forwardScan[index]=1;
} else {
forwardScan[index]=0;
}
} else {
if (digitalRead(Sensor1)==LOW) {
reverseScan[N-1-index]=1;
} else {
reverseScan[N-1-index]=0;
}
}
if (stepCount>stepTrip) {
stepCount=0;
dirFlag=1-dirFlag;
if (dirFlag==1) {
digitalWrite(DirZ,HIGH);
} else {
digitalWrite(DirZ,LOW);
}
scanDone=true;
}
}
}
}
void setup()
{
// LED
pinMode(LED_BUILTIN,OUTPUT);
pinMode(DirZ,OUTPUT);
pinMode(StepZ,OUTPUT);
pinMode(Enable,OUTPUT);
pinMode(Sensor1,INPUT_PULLUP); // Sensor1 is open collector
digitalWrite(LED_BUILTIN,HIGH); // Off
digitalWrite(DirZ,LOW);
digitalWrite(StepZ,LOW);
digitalWrite(Enable,LOW); // On
// Use Timer 2 for ISR
// Good for ATmega48A/PA/88A/PA/168A/PA/328/P
cli();
TIMSK2=0; // Clear timer interrupts
TCCR2A=(0<<COM2A0)|(0<<COM2B0)|(3<<WGM20); // Fast PWM
TCCR2B=(1<<WGM22)|(2<<CS20); // 2 MHz clock and (Mode 7)
OCR2A=243; // Set for 8197 Hz
OCR2B=121; // PWM 50% - Not used
TIMSK2=(1<<TOIE2)|(0<<OCIE2A)|(0<<OCIE2B); // Set interrupts
sei();
Serial.begin(9600);
delay(200);
// Pause to align scanner
Serial.println("Little Monster Scanner V1.0");
Serial.flush();
Serial.println("Waiting 10s for alignment of scanner");
Serial.flush();
delay(10000);
// Update frequency without interrupt (Note frequency should be between 1 and 4095)
unsigned int freq=400; // Using 400 step motor and 1/16 microsteps
cli();
magic=(freq<<3);
sei();
}
void loop()
{
int i,tmp,cnt,mean;
if (scanDone) {
scanDone=false;
mean=0;
cnt=0;
for(i=0;i<N;i++) {
tmp=reverseScan[i]+forwardScan[i];
mean+=i*tmp;
cnt=cnt+tmp;
}
if (cnt>0) {
mean=mean/cnt;
} else {
mean=N/2;
}
for(i=0;i<mean;i++) Serial.print('.');
if (cnt>0) {
Serial.print('*');
} else {
Serial.print(':');
}
for(i=mean+1;i<N;i++) Serial.print('.');
Serial.println();
}
}
An ISR runs the stepper motor and the mean uses forward and reverse scans.
Here is me sitting in my partners chair:
Little Monster Scanner V1.0 Waiting 10s for alignment of scanner .........:......... .........:......... .........:......... .........:......... Behind scanner (no signal) ...........*....... Walking to seat (crossing scanner path) .........*......... Seated (scanner centred on seat) .........*......... Seated (scanner centred on seat) .........*......... Seated (scanner centred on seat) ........*.......... Walking left of scanner ........*.......... Wakling left of scanner .........:......... Behind scanner (no signal) .........:......... .........:.........
So it is now ready (except for the controller box) to drive some spooky head(s).
AlanX
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.