Serial LCD project, PC temps, room temps, Time/Date, Email notifier

THE PROJECT:
An Atmel368 with a UNO boot loader.
Use RS232 to send computer stats and email notifications to Arduino.
C# for program on computer collecting and sending serial data.
Arduino will display info on LCD

-4x20 Serial LCD to display
     -PC Temps, room temps
           -PC Temps(CPU, GPU etc) using AIDA64, a windows app, has shared memory, any program can access temperature data.
           -LM35 for room temp, maybe real time outside temps later.
     -Time/Date, Email notification
           -Notifications=00 for none, 01 for 1 email waiting etc
           -ds1307rtc
     -Later
           -Get Stats from VLC(media player on computer) title, time remaining, time elapsed, total length, volume, and status- playing/paused etc

the first to bullets in the code boxes would be two different "tabs" of the screen. im going to use 2 momentary switches below the LCD so that when they are pressed the LCD displays the info under that "tab". another switch is pressed: causes other info to be displayed.

What is happening:
-Software/Programming(DONE!)
-Build the Arduino, wire everything up etc.(DONE!)
-Fix Pin configs (In Progress)

ARDUINO CODE
see 2nd reply, code too long.

COMPLETE C# CODE
see 4th reply, code too long.

Plan for PC temps and email:
A program in C# that gets data from gmail and it sends over serial has how many emails i have waiting. Ill get the temps data from AIDA via shared memory. so how to get this data to AVR? have a standard string of data with a "<" at the beginning so that the arduino knows when the data has begun to transfer across serial, and a ">" at the end so the end of the data is known. for example: first two numbers email, second two numbers cputemps, third set GPU temps etc. so it may look like "<02,30,50>" 2 emails, 30C CPU, 50C GPU. i hope to never have more than 99 emails or core temp higher than 99 so two digits per part. if emails is 00 then no email.

__Email and PC Temps:[c/b]__[/u]
C# program and coordinating arduino program that uses serial to communicate. computer sends how many notifications in number form to arduino. I have successfully got this program to fully work!
source: email notifications with arudino in C#
AIDIA64(perviously known as Everest) has a very simple shared memory. it stores the data as a XML like file in shared memory. I have succeeded at writing only the data i need from memory over serial. I have successfully got this program to fully work!
Source: reading memory mapped files .net 4.0

It doesn't sound to me like you have any idea what you want to do, or what you can do. Pick some specific aspect of the stuff you are rambling on about, and do that first. Then, add on. If you try to do everything at once, you'll end with with nothing working, and no clue as to why.

So, what part do you want to start with?

First post too long :D, so here is the rest/additions.
COMPLETE ARDUINO CODE
DONE!

#include <Time.h>  
#include <Wire.h>  
#include <DS1307RTC.h>// a basic DS1307 library that returns time as a time_t
#include <SoftwareSerial.h>

#define txPin 1

SoftwareSerial LCD = SoftwareSerial(0, txPin);
// since the LCD does not send data back to the Arduino, we should only define the txPin

const int LCDdelay = 5;    // conservative, 2 actually works
const int sensorPin = 3; //the analog pin the TMP35's Vout (sense) pin is connected to

const int buttonPin = 2;     // the number of the pushbutton pin
int counter = 0; // switch not pressed
int currState = LOW;
int prevState = LOW;

const int buttonPin2 = 4;     // the number of the pushbutton pin
int counter2 = 0; // switch not pressed
int currState2 = LOW;
int prevState2 = LOW;

int started = 0;
int inData[12];
int ended = 0;
char index = 0;
int final = 0;

// wbp: goto with row & column
void goTo(int row, int col) {
  LCD.print(0xFE, BYTE);   //command flag
  LCD.print((col + row*64 + 128), BYTE);    //position 
  delay(LCDdelay);
}
void clearLCD(){
  LCD.print(0xFE, BYTE);   //command flag
  LCD.print(0x01, BYTE);   //clear command.
  delay(LCDdelay);
}
void backlightOn() {  //turns on the backlight
  LCD.print(0x7C, BYTE);   //command flag for backlight stuff
  LCD.print(157, BYTE);    //light level.
  delay(LCDdelay);
}
void backlightOff(){  //turns off the backlight
  LCD.print(0x7C, BYTE);   //command flag for backlight stuff
  LCD.print(128, BYTE);     //light level for off.
   delay(LCDdelay);
}
void serCommand(){   //a general function to call the command flag for issuing all other commands   
  LCD.print(0xFE, BYTE);
}


void setup()  {
  pinMode(txPin, OUTPUT);
  LCD.begin(9600);
  clearLCD();
  
  Serial.begin(9600);
  
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet)
  {
     goTo(0,0); 
     LCD.print("Unable to sync with the RTC");
  }   
  else
  {
     goTo(0,0);
     LCD.print("RTC has set the system time");     
     delay(250);
     clearLCD();
  }
  timeStatus_t timeStatus();   
}

void loop()
{
   currState = digitalRead(buttonPin);
   if(currState == HIGH && prevState == LOW) // State just changed
      counter++;

   prevState = currState;

   if(counter > 1) counter = 0;
   {     
           //call get time stuff
      digitalClockDisplay();  

     //temp stuff
      //getting the voltage reading from the temperature sensor
      int reading = analogRead(sensorPin);  
    
      // converting that reading to voltage, for 3.3v arduino use 3.3
      float voltage = reading * 5.0;
      voltage /= 1024.0; 
    
      // print out the voltage
      //Serial.print(voltage); Serial.println(" volts");
    
      // now print out the temperature
      float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
      //to degrees ((volatge - 500mV) times 100)
      //Serial.print(temperatureC); Serial.println(" degress C");
    
      // now convert to Fahrenheight
      int temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
      goTo(2,0);
      LCD.print(temperatureF); 
      LCD.print(" degrees F");
      delay(1000);          //waiting a second
   } 
   
   
   //button2
   currState2 = digitalRead(buttonPin2);
   if(currState2 == HIGH && prevState2 == LOW) // State just changed
      counter2++;

   prevState2 = currState2;

   if(counter2 > 1) counter2 = 0;
   {  
     while(Serial.available() > 0)
       {
        char aChar = Serial.read();
        if(aChar == '<')
          {
            started = true;
            index = 0;
            inData[index] = '\0';
          }
        else if(aChar == '>')
          {
            ended = true;
          }
      
          else if(started)
          {
            inData[index] = aChar;
            index++;
            inData[index] = '\0';             
            }
        
          else if (aChar =='*')
            {
              final = true;
            }
       }
 

     if(started && ended)
       {
        const char*  strDelimiter = ",";

        char* p;
        char str[12] = {index}; //34,50,333,
        int CPU = 0;
        int GPU = 0;
        int FrMem = 0;

        if ( p = strtok(str, strDelimiter) )     { CPU = atoi(p); }
        if ( p = strtok(str, strDelimiter) )    { GPU = atoi(p); }
        if ( p = strtok(str, strDelimiter) )    { FrMem = atoi(p); }
        
          // Get ready for the next time
        started = false;
        ended = false;

        index = 0;
        inData[index] = '\0';      
       }  
   }
}

void digitalClockDisplay(){
  // digital clock display of the time
  goTo(0,0);
  LCD.print(hour());
  printDigits(minute());
  printDigits(second());
  LCD.print(" ");
  LCD.print(day());
  LCD.print(" ");
  LCD.print(month());
  LCD.print(" ");
  LCD.print(year()); 
  LCD.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  LCD.print(":");
  if(digits < 10)
    LCD.print('0');
  LCD.print(digits);
}

if some one could explain the errors

What errors? You haven't posted any of the errors you are getting.

but i cant for the life of me to get either of them to compile!!!!

I almost hesitate to ask where/how you are trying to compile these.

C# COMPLETE CODE
DONE!

using System;
using System.Timers;
using System.Text;
using System.Xml;
using System.IO;
using System.IO.Ports;
using System.IO.MemoryMappedFiles;
using System.Net;

namespace Final
{
    public class Output
    {
        private static string timer1Value = string.Empty;
        private static string timer2Value = string.Empty;
        private static FormWithTimer timer1;
        private static FormWithTimer2 timer2;

        public static void Main()
        {
            timer1 = new FormWithTimer();
            timer2 = new FormWithTimer2();

            timer1.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);

            timer2.NewStringAvailable += new EventHandler<BaseClassThatCanRaiseEvent.StringEventArgs>(timer1_NewStringAvailable);
            Console.ReadLine();
        }

        static void timer1_NewStringAvailable(object sender, BaseClassThatCanRaiseEvent.StringEventArgs e)
        {
            //SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
            //port.Open();

            if (sender == timer1)
            {
                timer1Value = e.Value.ToString();
            }
            else if (sender == timer2)
            {
                timer2Value = e.Value.ToString();
            }

            if (timer1Value != String.Empty && timer2Value != String.Empty)
            {
                //port.Write("<" + timer1Value + timer2Value + ">");
                Console.WriteLine("<" + timer1Value + timer2Value + ">");
            }
        }

        public abstract class BaseClassThatCanRaiseEvent
        {
            public class StringEventArgs : EventArgs
            {
                public StringEventArgs(string value)
                {
                    Value = value;
                }

                public string Value { get; private set; }
            }

            public event EventHandler<StringEventArgs> NewStringAvailable;
            protected void RaiseEvent(string value)
            {
                var e = NewStringAvailable;
                if (e != null)
                    e(this, new StringEventArgs(value));
            }
        }

        public partial class FormWithTimer : BaseClassThatCanRaiseEvent
        {
            Timer timer = new Timer();

            public FormWithTimer()
            {
                timer = new System.Timers.Timer(180000);

                timer.Elapsed += new ElapsedEventHandler(timer_Tick); // Everytime timer ticks, timer_Tick will be called
                timer.Interval = (180000);             // Timer will tick evert 10 seconds
                timer.Enabled = true;                       // Enable the timer
                timer.Start();                              // Start the timer
            }

            void timer_Tick(object sender, EventArgs e)
            {
                var url = @"https://gmail.google.com/gmail/feed/atom";
                var USER = "usr";
                var PASS = "pass";

                var encoded = TextToBase64(USER + ":" + PASS);

                var myWebRequest = HttpWebRequest.Create(url);
                myWebRequest.Method = "POST";
                myWebRequest.ContentLength = 0;
                myWebRequest.Headers.Add("Authorization", "Basic " + encoded);

                var response = myWebRequest.GetResponse();
                var stream = response.GetResponseStream();

                XmlReader reader = XmlReader.Create(stream);
                System.Text.StringBuilder gml = new System.Text.StringBuilder();
                while (reader.Read())
                    if (reader.NodeType == XmlNodeType.Element)
                        if (reader.Name == "fullcount")
                        {
                            gml.Append(reader.ReadElementContentAsString()).Append(",");
                        }
                RaiseEvent(gml.ToString());
            }

            public static string TextToBase64(string sAscii)
            {
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                byte[] bytes = encoding.GetBytes(sAscii);
                return System.Convert.ToBase64String(bytes, 0, bytes.Length);
            }
        }

        public partial class FormWithTimer2 : BaseClassThatCanRaiseEvent
        {
            Timer timer = new Timer();

            public FormWithTimer2()
            {
                timer = new System.Timers.Timer(1000);

                timer.Elapsed += new ElapsedEventHandler(timer_Tick2); // Everytime timer ticks, timer_Tick will be called
                timer.Interval = (1000);             // Timer will tick evert 10 seconds
                timer.Enabled = true;                       // Enable the timer
                timer.Start();                              // Start the timer
            }

            void timer_Tick2(object sender, EventArgs e)
            {
                using (var file = MemoryMappedFile.OpenExisting("AIDA64_SensorValues"))
                {
                    using (var readerz = file.CreateViewAccessor(0, 0))
                    {
                        var bytes = new byte[195];
                        var encoding = Encoding.ASCII;
                        readerz.ReadArray<byte>(0, bytes, 0, bytes.Length);

                        StringReader stringz = new StringReader(encoding.GetString(bytes));

                        var readerSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
                        using (var reader = XmlReader.Create(stringz, readerSettings))
                        {
                            System.Text.StringBuilder aida = new System.Text.StringBuilder();
                            while (reader.Read())
                            {
                                using (var fragmentReader = reader.ReadSubtree())
                                {
                                    if (fragmentReader.Read())
                                    {
                                        reader.ReadToFollowing("value");
                                        //Console.WriteLine(reader.ReadElementContentAsString() + ",");
                                        aida.Append(reader.ReadElementContentAsString()).Append(",");
                                    }
                                }
                            }
                            RaiseEvent(aida.ToString());
                        }
                    }
                }
            }
        }
    }
}

As you click on each of the errors, the offending line of code will be highlighted. Start with the 4th message. Resolving that may make the others go away.

as u am prettyt much a copy and paste coder, i have started to learn how to copy and paste code :smiley:

i added:

namespace GmailNotifier
{
    class Gmail
    {

then inserted the code under the class :slight_smile:

and added

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Text;
using System.Net;
using System.Runtime.InteropServices;

before all of it one error left

catch Console.WriteLine("Error… HttpWebResponse");

{ expected
fixed by:

catch
            {
                Console.WriteLine("Error… HttpWebResponse");
                return response;

            }

OK the last error i get because of the previous fix:
see pic

If an exception is thrown, the response variable does not contain valid data, but you return it, anyway.

If no exception is thrown, the response variable does contain valid data, but you do not return it. Why is that?

thats how the code was where i got it :smiley:

what you said gave me an idea.
i added "return response;"
in here:

private static XmlDocument GetGmailFeed(string userName, string password)
        {

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://mail.google.com/mail/feed/atom/");
            req.Method = "GET";
            req.Credentials = new NetworkCredential(userName, password);
            XmlDocument response = new XmlDocument();
            HttpWebResponse resp;
            try
            {

                resp = (HttpWebResponse)req.GetResponse();
                if (resp.StatusCode == HttpStatusCode.OK)
                {

                    XmlTextReader reader = new XmlTextReader(resp.GetResponseStream());
                    response.Load(reader);
                    reader.Close();

                }
                resp.Close();
                return response;

            }
            catch
            {
                Console.WriteLine("Error… HttpWebResponse");
                return response;

            }
        }

under resp.Close();

is taht what you mean? it compiles now :slight_smile:

is taht what you mean?

Yes, it is.

Although, in the catch block, you should probably return something other than response. Or set response to something that indicates that an error occurred before returning it.

ive done alot of stuff, new info in first post.

i have a question. in the code in found for Arduino to read the incoming serial data, "if(Serial.available() >= 8){" is that saying serail is available when data received is greater than or equal to 8?

also when im sending this data to the arduino (30,50,40 etc) can i add a "H" or something before and after the string sent from the computer so that the arduino knows when it has the whole string: H,30,50,40,H ? how would i implement that in the arduino code? something like reply 5 in http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226107230/3 but i don't understand that code.

or am i overly worried? and the data will always get to the arduino?

thanks

EDIT\ DOH in the if(Serial.available() >= 8){ the smiley is an 8

if(Serial.available() >= 8)

The Serial.available() function returns the number of bytes (characters) in the serial buffer that have not yet been read.

The if test is saying "Do this if there are 8 or more bytes to be read", where "this" is the stuff in the curly braces that follow.

also when im sending this data to the arduino (30,50,40 etc) can i add a "H" or something before and after the string sent from the computer so that the arduino knows when it has the whole string: H,30,50,40,H ?

Could and should. Some kind of start and end of packet markers makes reading serial data so much easier. No need to wait for all the data to arrive, when you don't know how much data "all the data" is, and when serial data delivery is not guaranteed.

how would i implement that in the arduino code?

I've posted examples of how to read data using start and end of packet markers. Search for "started && ended".

but i don't understand that code.

That's not the best way to read serial data, in my opinion, because it blocks until a complete packet arrives. It's much better to collect the data as it arrives, and process it when the complete packet has been received. But, it works if you know how many bytes of data make up a packet.

You don't, so you can't use it.

But, what it does is loop to read bufsize characters from the serial port, and add each character to the next position in an array (buf). It waits until there is at least one character to read before each read operation (which is what makes it a blocking function). After reading bufsize characters, it adds a NULL at the end of the array of characters, so the array is a NULL-terminated array of characters, also known as a string (lower case s to distinguish it from a String instance).

i cant find your post about started && ended. i found others asking bout it but not the actual topic. could you link? thanks

Here's one example:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1277154707

so i finally got my diyduino built with a atmega328, but i got a probably really noobish question on the sensor/TX etc pins.

ok so i have a DS1307 RTC, LM35 temp probe, serail lcd, and RX pins and buttons connected on:

DS1307: i2c ardunio pins SCL/SDA (analog 5, 4) 
LM35: arduino pin 3 analog
Serial LCD: arduino digital pin 1 (TX) 
Output (TX) from computer to max232 to arduino RX pin (digital 0)
button: arduino digital pin 2
button2: arduino digital pin 3

im guessing i dont need to declare any pins for the DS1307 since its i2c and im using the RTClib.h library?

thanks

just an update:
i have everything done, coding (C# and Arduino!), its all wired up on a breadboard, pin configs, and all i have to do is hook it up and program it!

ill get some pics when its running.

i have one question still (besides the ds1307 pin question from the previous post). i have a SP3232e (like a MAX232) for serial programming and receiving data from the computer. should there be only one serial cable data pin (the computer TX pin) going into the SP3232e IC? no other serial pins from the computer? and then just the RX pin hooked up from the SP3232e to the Arduino? im talking just data of course not vcc and the caps that are required for the IC to function.

thanks

im guessing i dont need to declare any pins for the DS1307 since its i2c and im using the RTClib.h library?

No, you don't. Analog pins are input only, so the mode doesn't need to be declared. I2C uses the pins differently, and there is no I2C mode, so, again, there is no need to declare any mode.

i have a SP3232e (like a MAX232) for serial programming and receiving data from the computer.

Are you using a real serial port? Most serial communication is done using the USB-to-serial converter chip, which inputs/outputs at TTL levels already.

yes a real serail port. :slight_smile: pretty rare right...

do i need both TX and RX communication between my computer and the arduino to program it via serial? it has uno bootloader.

thanks

do i need both TX and RX communication between my computer and the arduino to program it via serial? it has uno bootloader.

A quick peak in the Installation and Troubleshooting forum would show that this message is quite common:

avrdude: stk500_getsync(): not in sync: resp=0x00
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x51

As you can see, the avrdude command talks to the Arduino (via its RX line) AND expects a response (from its TX line).

So, yes, you need both.