Hi guys,
I need some help - I have a fencing scoring machine that I am trying to duplicate from this one
http://www.sonic.net/~schlae/gplscoremach.html
I started out with that same wiring - but could not get good logic 0s. No matter how I set things up everything read in as 1 because the resisters acted like voltage dividers and I couldn't get down to 0.8V for a low. Finally gave up, now have the output lines going thru an open collecter 7406 with 3.3K pullup resistor. Now an output can be grounded and its good & low because it doesn't have an active driver & a resistor in the way. I have 74F374 with 24mA current sink driving the cathode of LEDs low to turn them on (don't have any shift registers handy, guess I should order some).
The problem I am having is below.
I am working the code for Epee weapons. An epee has 2 wires, A & B, that end at a switch at the tip of the blade. When the tip is closed, A & B are connected. If the switch is closed against ground (metallic floor strip, or opponents bellguard), then B & A will have 0 on them.
I have it coded to drive a low signal onto the C wires (opponents Bellguard), and toggle a hi/lo signal onto the B wires. I then read the B wires to see that they are not grounded, and if they are to turn on a ground light for as long as it reads a 0 when it should be a 1.
I can't get that to work - I think I have a s/w logic error, but can't see what it is. With a scope I can see a good 0 at the input.
I also have an issue whereby when the switch is closed for a good touch, then occasionally the touch light goes on & stays on, and won't turn off by itself, but only after a touch on the other side. The code requires the A&B input to match the B output for 30 consecutive reads, which at 106-110uS worked out to 2ms. At 200uS will be ~4mS.
I thought it was a race condition, so I lengthened the interval time of my loop from 100uS to 200uS. Didn't make a difference.
Could use another set of eyes to see what is going on.
Thanks
Robert
// I didn't copy all the pin definitions, takes up a lot of space. This is the part that is running in void loop(). No interrupts, no functions.
// start timing interval
unsigned long currentMicros = micros(); // see how long its been
if (currentMicros - previousMicros >= hundred_uS_interval) // more than our 0.2mS interval?
{
// save the last time we okayed time updates
previousMicros = currentMicros;
if (toggle == 0){
toggle = 1;
}
else {
toggle = 0;
}
// this ~ (bitwise not) does not seem to work:
// toggle = ~toggle; // try odd/even kind of thing for sending high/low from outs to ins
// do stuff on 0.1mS intervals, 1mS intervals, ets.
// *****************************************************************
switch(Weaponmode)
{
case 1: // epee
// need contact for 2mS to 10mS to score
// double touch if 2nd fencer has contact for 2ms within 40mS to 50mS of 1st fencer
// gnd light if contact against opponents bellguard
// or to grounded strip
// On Toggle High, put out a 0 on ResBwires
// On Toggle Low, open collector output is pulled up to a 1
// Read WireB, if low when ResWire says high, then output is grounded
// Read WireA & WireB, if they follow ResBWire for 30 occurrences (Hi-Lo-Hi-Lo) then call it
// a touch, turn on light via shift register
// if WireB grounded in the middle, start over
if (toggle == 1){
digitalWrite (ResBWireL, HIGH); // high on Left B wire -> 0 with 7406
digitalWrite (ResBWireR, HIGH); // high on Right B wire -> 0 with 7406
ResBstate = 0;
}
else {
digitalWrite (ResBWireL, LOW); // low on Left B wire -> 1 with 7406
digitalWrite (ResBWireR, LOW); // low on Right B wire -> 1 with 7406
ResBstate = 1;
}
delayMicroseconds(25); // << play with this with reels, see if long enough
// signal delay ~1 ns/foot. From uC floor cord to reel to body cord to tip ~30 meters, 90 feet, & back, 180 feet = 180nS, 0.18uS
// now read the wires
leftA = digitalRead(AWireL); //
leftB = digitalRead(BWireL); //
rightA = digitalRead(AWireR); //
rightB = digitalRead(BWireR); //
// *****************************************************************
// check if left is grounded
if (ResBstate == 1 && leftB == 0) // no touch for left, show ground light for duration
{
outdata = outdata & 0b1111111111011111; // AND out the ground light to turn it on
left_contact_count = 0; // reset the contact count
}
if (ResBstate ==1 && leftB == 1) // turn it off, not grounded
{
outdata = outdata | 0b0000000000100000; // OR in the ground light to turn it off
}
// check if right is grounded
if (ResBstate == 1 && rightB == 0) // no touch for right, show ground light for duration
{
outdata = outdata & 0b1111111111111011; // AND out the ground light to turn it on
right_contact_count = 0; // reset the contact count
}
if (ResBstate ==1 && rightB == 1) // turn it off, not grounded
{
outdata = outdata | 0b0000000000000100; // OR in the ground light to turn it off
}
if (old_outdata = outdata) // if data changed, send it out
{
// not changed, do nothing
}
else{
shiftOut(shiftdataout, serialclock, MSBFIRST, (outdata >> 8)); // shift it out
shiftOut(shiftdataout, serialclock, MSBFIRST, outdata); // shift it out
}
old_outdata = outdata;
/*
Look for a left touch, see if contact held for 30 hi/lo cycles (just over 2ms)
Look for a right touch, see if contact held for 30 hi/lo cycles
If either 2mS completes set a corresponding flag, either one starts the 40mS lockout timer.
At the end of 40mS turn on the score light for the flags that are set.
*/
if (leftB == ResBstate && leftA == ResBstate && left_main_timer_running == 0) // start left contact count
{
left_contact_count = left_contact_count + 1;
}
else
{
left_contact_count = 0;
} // case when leftA<>ResBstate i.e. no tip closure
if (rightB == ResBstate && rightA == ResBstate && right_main_timer_running == 0) // start right contact count
{
right_contact_count = right_contact_count + 1;
}
else
{
right_contact_count = 0;
} // case when rightA<>ResBstate i.e. no tip closure
// did left have enough matching contacts?
if (left_contact_count == 30) // check left contact count
{
goodlefttouch = 1; // set flag for a good left touchh
outdata = outdata & 0b1111111001111111; // AND out the bit to turn it on
shiftOut(shiftdataout, serialclock, MSBFIRST, (outdata >> 8));
shiftOut(shiftdataout, serialclock, MSBFIRST, outdata);
left_main_timer = millis(); // start 40mS timer
left_main_timer_running = 1; // flag for 40mS timer running
left_contact_count = 0; // reset for next pass
}
// did right have enough matching contacts?
if (right_contact_count == 30) // check right contact count
{
goodrighttouch = 1; // set flag for a good right touch
outdata = outdata & 0b1111111011101111; // AND out the bit to turn it on
shiftOut(shiftdataout, serialclock, MSBFIRST, (outdata >> 8));
shiftOut(shiftdataout, serialclock, MSBFIRST, outdata);
right_main_timer = millis(); // start 40mS timer
right_main_timer_running = 1; // flag for 40omS timer running
right_contact_count = 0; // reset for next pass
}
if (goodlefttouch == 1){
left_main_timerend = millis(); } // check the 40mS timer
if (goodrighttouch == 1){
right_main_timerend = millis();
} // check the 40mS timer
// <<< tried micro() for this 40mS part, would never enter the next if condition (>40000) to
// turn things off after a touch
if (left_main_timerend - left_main_timer > 40 || right_main_timerend - right_main_timer > 40)
{
delay (2000); // leave lights & buzzer on for 2 seconds
goodlefttouch = 0; // reset for next pass
left_main_timer_running = 0;
left_main_timer = 0;
left_main_timerend = 0;
goodrighttouch = 0; // reset for next pass
right_main_timer_running = 0;
right_main_timer = 0;
right_main_timerend = 0;
outdata = 0b1111111111111100; // turn everything off except Epee indicator lights
shiftOut(shiftdataout, serialclock, MSBFIRST, (outdata >> 8));
shiftOut(shiftdataout, serialclock, MSBFIRST, outdata);
}
break;// end of case: epee
// *******************************************************************
} //end of Switch (Weaponmode)
} // end of time interval