Help needed to convert some code.

OK, a bit of background here. A few years ago, I bought a Velleman K8055 USB interface board and whilst tinkering with it, I developed a rather nice quiz buzzer program for it.

Fast forward to today and I start hearing about Arduino, so I order a Duemilanove to tinker with, hoping to convert my quiz buzzer program over to it, thinking that it shouldn't be too hard...

Well, it turned out to be more difficult than I thought and I could use a little help from the community with it.

Here's the original code:

#include <stdio.h>
#include <iostream>
#include "K8055D_C.h"
#include "resource.h"
#include "conio.h"
#include <cstdlib>
#include "windows.h"

using namespace std;

void CheckInputs(bool screen = true);   // passes a true value to screen
                                        // and sets CheckInputs to perform                                        
bool inputflag = false;                 // the initial input error check
bool exitflag = false;
int x;

int main()
{
      // open communication with K8055D
      OpenDevice(0);

      // check for sticky inputs
      CheckInputs();

      cout << "Initial Check Complete" << endl;
      cout << "Enter number of questions: ";
      cin >> x;
      cout << "Press any key to continue...";
      _getch();
      system("CLS");      
      for (int i = 0; i < x; i++)
      {
        // cout << i; // used for testing purposes
        
          do
          {
                CheckInputs(false);
    
                if (ReadDigitalChannel(5)) 
                {
                      ClearAllDigital();
                      system("CLS");
                      inputflag = false;
                      exitflag = true; // get out of do...while loop
                }
          } while (exitflag == false); // loop while button 5 is not depressed
          
          while (ReadDigitalChannel(5));
          
          exitflag = false;
    }

      ClearAllDigital();
      cout << "Press any key to exit...";
      _getch();
      
      CloseDevice();
      return 0;
}

void CheckInputs(bool screen)           
{                                       
      for (int i = 1; i <= 5; i++)        
      {                                   
            bool inputstatus = false;       

            inputstatus = ReadDigitalChannel(i);

            if (inputstatus)
            {
                  if (screen) // If at program start, check for stuck inputs
                  {
                        cout << "Input " << i << " depressed" << endl;      
                        inputflag = true;   // Lock inputs 1-4
                  }
                  else
                  {
                        if (i != 5)         // If input 5 not pressed and
                              if (!inputflag) // if no inputs locked
                              {
                                    SetDigitalChannel(i); // Set corresponding output
                                    cout << "Contestant " << i << " buzzed!" << endl;
                                    PlaySound("buzzerheavy.wav", NULL, SND_ASYNC);
                                    inputflag = true;   // Lock inputs 1-4
                              }
                              else;
                        else;
                  }
                  
            }
            else;
      }

      if (!inputflag && screen)  // If program starts 
                                               // with no stuck inputs
      {
            cout << "No inputs depressed\n" << endl;
            ClearAllDigital();
      }
      else;

      return;
}

That's the PC end of your program - you need to read about how to write sketches for the Arduino.

There are tutorials and examples over at the main Arduino site.

Yes, I am aware of this. I know that loop() and setup() take the place of main() and get compiled to main() in the final uploaded code.

My main sticking point seems to be that there's no function equivalent to the K8055's ClearAllDigital() in Arduino, but also general problems with syntax matching.

Essentially, CheckInputs() is a Swiss Army Knife routine that performs different functions depending on where in the program it is called and what data is passed to it.

During the initial program startup, it checks that all the inputs are clear, then shifts to detecting buzzer presses and locking out other players. Finally, it checks to see if the reset button has been pressed by the quizmaster.

I'm confused - are you aiming to run the Arduino as simply an I/O board, and handle the interface on the PC, or do you want to do it all on the Arduino, via the serial interface?

I want to run it all on the Arduino via the serial interface. Eventually, I want to make it self contained, using an LCD display to control everything, but for now I just need to get as close as possible to the original program as I can.

I don't know anything about this Velleman board, but you need to initialise a set of input pins and a corresponding set of output pins.
"ReadDigitalChannel" becomes "digitalRead", and "setDigitalChannel" becomes "digitalWrite".
There is no "clearAll" - you just loop through the pins and write them to whatever you want.
Work through some of the examples, and see how you get on.

PlaySound is going to be a problem, unless you have a sound shield.

At the moment, playing a buzzer sound is not important.

One thing I did notice is that because you have to set up a constant for each input, something like this:

digitalRead (buttonPin(i));

won't work, unless I'm missing something blindingly obvious.

Assuming "buttonPin" is a function that returns an integer datatype, yes, that will work.

Except that I need to declare 5 input pins, so I would need to declare:

int buttonPin1 = 2;
int buttonPin2 = 3;
int buttonPin3 = 4;
int buttonPin4 = 5;
int buttonPin5 = 6;

Unless I can assign a variable to a single buttonPin declaration in order to step through the pins iteratively.

Essentially, what the K8055 ReadDigitalChannel() function does is scan the input bus for changes to a specific channel number, but you can scan multiple channels at once by feeding it a variable instead of a channel number and stepping through iteratively.

Yes, if you want you can have a single array of button pin numbers.

Have a look at the tutorials and examples.

Ah, so if I use:

int buttonPins[] = {2, 3, 4, 5, 6};

I can use that to step iteratively through the input scanning routine?

I'd prefer to see const int buttonPins[] = {2, 3, 4, 5, 6};
but yes, that will work.

So, CheckInputs would be:

void CheckInputs (boolean screen)
{
  int i;
  for (i = 2; i <=6; i++)
  {
    boolean inputstatus = false;
    
    inputstatus = digitalRead(buttonPins[i]);
    
    if (inputstatus)
    {
      Serial.println("Input " i " depressed");
      inputflag = true;
    }
    else
    {
      if (i != 6)
        if (!inputflag)
        {
          Serial.println("Contestant " i-1 " buzzed!");
          inputflag = true;
        }
        else;
      else;
    }
  }
  else;
  
  if (!inputflag && screen)
  {
    Serial.println("No inputs depressed");
  }
  else;
  
  return;
}

Not every if statement needs an else. If the else is not doing anything, get rid of it.

The else; look like errors. At least, errors waiting to happen.

digitalRead(buttonPins[glow][[/glow]i[glow]][/glow]);

It's an array, not a function.

Not much point initiailising the flag, if you're going to overwrite it:

boolean inputstatus = digitalRead(buttonPins[i]);

Also, be careful, C subscripts normally start from zero.

Not every if statement needs an else. If the else is not doing anything, get rid of it.

These do. If you read through the function's logic you'll see that they are all dependent on one another. There was yet another if...else in there, but I managed to refactor them into one. Unfortunately, that was the only one I have been able to refactor without breaking the logic. If you can find a way to reorganise it and have it perform the same function, I would appreciate the help.

The else; look like errors. At least, errors waiting to happen.

The original code compiles with no errors, so I transposed it almost verbatim, editing for the differences in syntax between C and Arduino. If the Arduino compiler throws a hissy fit, it's due to its interpretation of the C language, not my initial code.

It's an array, not a function.

Good catch, thanks.

Not much point initiailising the flag, if you're going to overwrite it:

Unless of course, you need it resetting at the beginning of each loop.

The "else;"s do nothing - the fact that there's a semicolon after them signals that.
They are redundant, as is the "return;".

Unless of course, you need it resetting at the beginning of each loop.

But you overwrite it at the beginning of every loop!

Just because a bit of code compiles without errors doesn't mean it doesn't harbour potential nasties.
Most languages allow you to shoot yourself in the foot, but C hands you the gun.
If you cut out redundant code, you leave fewer dark corners for the bugs to hide.

The "else;"s do nothing - the fact that there's a semicolon after them signals that.
They are redundant, as is the "return;".

So they are, just test compiled the original code without them and it returned no errors.

But you overwrite it at the beginning of every loop!

D'oh!

Just goes to show how useful it is having an objective pair of eyes go over your code, lol.

void CheckInputs(boolean screen = true);  //passes a true value to screen
                                          //and sets CheckInputs to perform
                                          //the initial input check.

boolean inputflag = false;                //the initial input error check
boolean exitflag = false;
int x;
const int buttonPins[] = {2, 3, 4, 5, 6};

void setup()
{
    Serial.begin(9600);
}

void loop()
{
  
  CheckInputs();
  
  Serial.println("Initial Check Complete");
  Serial.println("Enter number of questions");
  x = Serial.read();
  
  for (int i = 0; i < x; i++)
  {
    do
    {
      CheckInputs(false);
      
      if (digitalRead(buttonPins[6]));
      {
        for (int a= 2; a <=6; a++)
          {
            digitalWrite(buttonPins[a], LOW);
          }
        inputflag = false;
        exitflag = true;
      } while (exitflag == false);
      
    while (digitalRead(buttonPins[6]));
      
    exitflag = false;
    }
    
    
  }
)

void CheckInputs(boolean screen)
{
  int i;
  for (i = 2; i <=6; i++)
  {
    boolean inputstatus = digitalRead(buttonPins[i]);
    
    if (inputstatus)
    {
      Serial.println("Input " i " depressed");
      inputflag = true;
    }
    else
    {
      if (i != 6)
        if (!inputflag)
        {
          Serial.println("Contestant " i-1 " buzzed!");
          inputflag = true;
        }
    }
  }
   
  if (!inputflag && screen)
  {
    Serial.println("No inputs depressed");
  }
  
}

OK, so this is how far I've got so far.

This doesn't compile, right?

It has errors around lines like:

Serial.println("Input " i " depressed");

which are not legal C or C++.

This would need to become

Serial.print("Input ");
Serial.print( i );
Serial.println(" depressed");

Also

  for (i = 2; i <=6; i++)
  {
    boolean inputstatus = digitalRead(buttonPins[i]);

is likely wrong, because the only valid indexes for buttonPins[] is 0 to 4.

HTH
GB