Turning LED on and off with C++ (using CPPWindows)

So, since I normally despise interpreted languages (Python being the sole exception so far), I've been trying to get an LED to blink on my Uno with C++ and a winform. With very similar code and the same circuit using Processing I was able to turn the LED on and off with two buttons from my computer, but am having no luck with C++.

I compiled CPPWindows to a static library and it works fine on its own; my program is the problem. I made a simple winform with two buttons, one to turn the LED on and the other off, but it does not function as intended. When I click either button, the RX light on the Uno lights up, so I know it's receiving data, but apparently not the right data. Here's what I have so far:

#include <Arduino\SerialClass.h>
#include "Send.h"
#include "led.h"

namespace ledtest {
	Serial* SP = new Serial("COM3");

	[STAThread]
	void main(array<String^>^ args) {

		Application::EnableVisualStyles();
		Application::SetCompatibleTextRenderingDefault(false);

		ledtest::led form;
		Application::Run(%form);
	}

	void sendState(int state) {
		if (state == 1)
			SP->WriteData("1", 1);
		if (state == 0)
			SP->WriteData("0", 1);
	}	
        
        void readState() {
		char* iState;

		while (SP->IsConnected()) {
			SP->ReadData(iState, 255);
			printf(iState);
		}
	}

The button click events are as follows:

	private: System::Void btnHigh_Click(System::Object^  sender, System::EventArgs^  e) {
				 ledtest::sendState(1);
			 }
	private: System::Void btnLow_Click(System::Object^  sender, System::EventArgs^  e) {
				 ledtest::sendState(0);
			 }

My Arduino sketch:

int led = 12;
char* state;

// the setup routine runs once when you press reset:
void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  if (Serial.available()) {
    Serial.readBytes(state, 1);
    
    if (state == "1")
      digitalWrite(led, HIGH);
    if (state == "0")
      digitalWrite(led, LOW);
    else {
      Serial.println(state);
    }
  }
}

CPPWindows' WriteData function requires char*, so that's why I am sending "1" instead of just a 1. In the sketch I read one byte (the character "1"), and then set the pin as high or low depending on the variable "state".

However, the data sent from the C++ program is apparently not sent correctly (or I am sending it incorrecty) and the LED never turns on. Also, the C++ program never prints what the actual variable is. Even if the variable from the Uno can't be read it should at least return a "-1", but it returns nothing.

I'm all out of ideas on what to do, so any help would be appreciated. Thanks!

'm all out of ideas on what to do

Ditch the convoluted Microslop abomination of C++, and use C# instead. Much easier to design forms, program callbacks, etc. AND support for the serial port is built in. Read and write like a file.

You insult Microsoft's C++, but you like C#, which they had much more to do with than C++? :stuck_out_tongue:

I guess I could use C#. I've used it in the past, but prefer sticking with C/C++ since it's much more easily cross-compiled. No need to worry about Mono.

And I realize this program is completely Windows dependent, but the more C++ experience I can get, the better.

So I can switch to C#, but if anyone could help me with this I'd much prefer that.

You insult Microsoft's C++, but you like C#, which they had much more to do with than C++?

Yes. What the hell is this?

	private: System::Void btnHigh_Click(System::Object^  sender, System::EventArgs^  e) {

An Object^ is not standard C++.

    Serial.readBytes(state, 1);

It hardly makes sense to use a function that can read multiple bytes to read one. Use read(), instead.

char* state;

state is a pointer. It doesn't point to anything. You can't pass a NULL pointer to readBytes() and expect it to write the data somewhere usable.

read() requires an int, and since WriteData() requires a char*, I don't know if that would work well.

Yeah, that's my bad. I haven't done any programming in about 3 months, and even then most of what I did was x86 assembly, so I've forgotten a lot of C++. I actually much prefer assembly over any other language; even though it's anything but terse, everything is explicit. I always have trouble understanding implicit, complex, convoluted things. But even then I was still an amateur programmer.

With MASM at least, once can initialize a variable of indeterminate size (in the .data? section, and the program can do with it as it pleases, so I guess I figured I could do the same here. :stuck_out_tongue:

Would char* state = new char[#] be correct? Or how would you recommend I send the data from my computer to the Arduino?

read() requires an int, and since WriteData() requires a char*, I don't know if that would work well.

read() doesn't require anything. It returns an int. The only reason it returns an int, instead of a char or byte, is to allow the function to return an error if there is nothing to read. You can cast the return to a char, implicitly or explicitly.

You can use readBytes() but not with a NULL pointer. You must make the pointer point somewhere first. The simplest method is to not use a pointer at all. Use an array, instead.

char state[2];

Serial.readBytes(state, 1);
if(state[0] == '1')
   // do the one thing
else if state[0] == '0')
   // do the zero thing

Well, I changed the sketch to what you provided, and it works. Thank you kindly.

However, I still can't get the ReadData() to work. Here's what I changed my program to:

	void readState() {
		char iState[2];

		while (SP->IsConnected()) {
			SP->ReadData(iState, 1);
			printf("%s", iState[0]);
		}
	}

And the sketch:

    if (state[0] == '1') {
      digitalWrite(led, HIGH);
      Serial.println(state[0]);
    }
    if (state[0] == '0') {
      digitalWrite(led, LOW);
      Serial.println(state[0]);
    }

The LED turns on and off as expected, but I still get no console output on my C++ program. Do you see anything glaringly obvious?

Serial.println(state[ 0 ]) sends three characters. You are attempting to read only one of them. That's not a good match.

What is supposed to trigger a call to readState()? Add a printf() to just print a message like "Hey, I got called!". Does that get printed?

Shit, you're right. That's what I get for staying up so long.

So after declaring the function and calling it from main, it still doesn't work. It only does when I close the winform, then the console works. Probably because both appear only because I have the subsystem unset. I'll find a different way to show the text in the program. If only I could figure out how to set the text of a textbox from the main source file...