Tuesday, March 13, 2012

I always say that I quit, but never do

When I made my last post I was about ready to quit this. The control board was acting stupid, I was unable to get any support for it, and I was getting pissed off considering it worked before and suddenly would not work after a server reboot. I have been pulling my hair out all week.

Well, I think I may have figured out a fix. I still don't understand WHY it does this and I still think it's some kind of bug, but by looking at different online examples of serial connectivity and copying code around, I changed my connect function to this:


bool SerialConnector::Open()
{
if(m_Path=="")
{
ScreenOutput("No path specified");
return false;
}



//init stuff

struct termios tio;
//struct termios stdio;
//int tty_fd;
//fd_set rdset;


//memset(&stdio,0,sizeof(stdio));
//stdio.c_iflag=0;
//stdio.c_oflag=0;
//stdio.c_cflag=0;
//stdio.c_lflag=0;
//stdio.c_cc[VMIN]=1;
//stdio.c_cc[VTIME]=0;
//tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
//tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
//fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking


memset(&tio,0,sizeof(tio));
tio.c_iflag=0;
tio.c_oflag=0;
tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
tio.c_lflag=0;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=5;


//connect
m_fd=open(m_Path.c_str(), O_RDWR | O_NONBLOCK);



cfsetospeed(&tio,B115200); // 115200 baud
cfsetispeed(&tio,B115200); // 115200 baud

//this is required, it seems that it only needs to be called once per server reboot. It sets some kind of global thing that prevents the serial device (in my test: uk1104 from canakit) to go insane and spam junk
tcsetattr(m_fd,TCSANOW,&tio);

if (m_fd == -1 )
{
ScreenOutput("Unable to connect");
m_conactive=false;
return false;
}

m_conactive=true;

return true;
}


I want to thank the author of this page:

https://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux

The example is straight to the point line by line and easy to follow. Most of the examples I found were terrible to figure out.

I don't really know what every single line of code does, but the key lines are these:






memset(&tio,0,sizeof(tio));
tio.c_iflag=0;
tio.c_oflag=0;
tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
tio.c_lflag=0;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=5;




cfsetospeed(&tio,B115200); // 115200 baud
cfsetispeed(&tio,B115200); // 115200 baud




In that order. I'm guesssing setting the baud rate may possibly play a role, but the code above also does. The connect function is the same as before.

It seems to me some of these parameters stick even after the program is done executing. I discovered that when I ran an example stand alone, and ran my program, my program worked. If I rebooted, my program stopped working. Oddly, running picocom did not actually set whatever global flags were being set, at least not permanently.

Either way, after several server reboots and several resets of the USB device it seems to work. Though, I may be calling it too early. I will let it run overnight before I take the app out of simulation mode, (basically this mode just ignores relay calls).

After tomorrow I will be off for 2 days, so I will run it live and see how it works out.

I really hope this works out on a long term basis, as I'm looking forward to actually putting this to good use and no longer need to keep messing with the thermostat programming day to day to accommodate my different shifts. This app is set and forget, which is awesome. It's why I did it. Given most people work standard shifts, consumer thermostats are designed for that, so I needed something to accommodate shift work.


Once this is proven, I will probably make up a full blown article explaining everything I did. Man, I'm so glad I got this working though, this spam thing was really starting to burn me.

No comments: