Refreshing a chart control - c#

This one is driving me a bit crazy. Any help gratefully received. It's a simple program to receive temperature data from an Arduino based temp sensor, and display it in a graph control on a form. The program works fine, and parses the temp data frame a treat. However..... the graph object doesn't refresh, and the whole point is to show the data over time. I thought that the chart1.DataBind command that I put in forced a refresh. I am using Visual Studio 2013 Express. Any thoughts as to what I am doing wrong very much appreciated.
// Start of program.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace serial_port_with_events_attempt_4
{
public partial class Form1 : Form
{
string RxString;
int RxRead;
int i;
int RxDec1;
int RxDec2;
int RxDec3;
float RxFloat;
float RxFloat2;
string locnString;
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
serialPort1.PortName = "COM8";
serialPort1.BaudRate = 9600;
serialPort1.Open();
if (serialPort1.IsOpen)
{
buttonStart.Enabled = false;
buttonStop.Enabled = true;
textBox1.ReadOnly = false;
}
}
private void buttonStop_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
buttonStart.Enabled = true;
buttonStop.Enabled = false;
textBox1.ReadOnly = true;
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxRead = serialPort1.ReadByte();
this.Invoke(new EventHandler(DisplayText));
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
}
private void DisplayText(object sender, EventArgs e)
{
if (RxRead == 126)
{
textBox1.AppendText(Environment.NewLine);
i = 0;
}
if (i< 23)
{
if (i == 7)
{
if (RxRead == 51) // 51 in this position means that the temp sensor is the one in the wooden box
{
textBox1.AppendText("Temperature in Nick's office = ");
locnString = ("Nick's office");
}
}
if (i == 17)
{
RxDec1 = RxRead - 48; // Read the tens unit
}
if (i == 18)
{
RxDec2 = RxRead - 48; // Read the units
}
if (i == 20)
{
RxDec3 = RxRead - 49; // read the decimal
}
if (i == 22)
{
RxFloat = ((RxDec1 * 10) + RxDec2);
RxFloat2 = RxDec3;
RxFloat2 = RxFloat2 / 10;
RxFloat = RxFloat + RxFloat2;
RxString = RxFloat.ToString();
if (RxFloat < 30 && RxFloat >20)
{
// Put the value in the main text box if it is not corrupt, (checking if the range is reasonable
textBox1.AppendText(RxString); // Frig about to get the reads in the right format and added together
// Add a new line into the temperature database
temperature1DataSetTableAdapters.Temp1TableAdapter temp1tableadapter = new temperature1DataSetTableAdapters.Temp1TableAdapter();
temp1tableadapter.Insert(DateTime.Now, RxFloat, locnString);
}
// Delete any old data.
temperature1DataSetTableAdapters.TempTableAdapter temp2tableadapter = new temperature1DataSetTableAdapters.TempTableAdapter();
temp2tableadapter.DeleteTempQuery();
// The above two lines work, but I need to amend to select on date TODO
chart1.DataBind();
}
}
i=i+1;
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'temperature1DataSet.Temp' table. You can move, or remove it, as needed.
this.tempTableAdapter.Fill(this.temperature1DataSet.Temp);
}
}
}
Cheers,
Nick James

Related

Incorrect calculation output

I am trying to create a simple form for calculating speed, distance and time traveled, but the calculations come out wrong.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace _2ndTask
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double speed, time, distance, laiks, garums, atrums; // laiks = time2, garums = distance2, atrums = speed2
private void label1_Click_1(object sender, EventArgs e)
{
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
bool timeInput = double.TryParse(textBox3.Text, out laiks);
if (!timeInput || laiks < 0 || laiks > 9999)
{
// MessageBox.Show("Ignorēt šo paziņojumu.");
}
// timeInput = float.Parse (textBox3.Text);
}
private void textBox2_TextChanged2(object sender, EventArgs e)
{
bool cGarumsInput = double.TryParse(textBox2.Text, out garums);
if (!cGarumsInput || garums < 0 || garums > 999999)
{
// MessageBox.Show("Ignorēt šo paziņojumu.");
}
}
private void textBox1_TextChanged_1(object sender, EventArgs e)
{
bool speedInput = double.TryParse(textBox3.Text, out atrums);
if (!speedInput || atrums < 0 || atrums > 9999)
{
// MessageBox.Show("Ignorēt šo paziņojumu.");
}
}
private void button2_Click(object sender, EventArgs e)
{
time = (garums / atrums);
label4.Text = time.ToString();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
distance = atrums * laiks;
label4.Text = distance.ToString() + " Km.";
}
private void button1_Click(object sender, EventArgs e)
{
speed = garums / laiks;
label4.Text = speed.ToString() + " Km/h.";
}
}
}
Before I added TryParse the calculations were correct, but the forms would crash whenever values would be deleted from textboxes.
It should output 140 underneath (multiply time and speed) instead it outputs 49. Inputting other numbers also gives wrong result
You have a typo. You are assigning the text from textBox3 to both atrums and laiks. Presumably one of them should use the text from textBox1.

Simon Game in C#

I've been creating the game Simon in a windows form using C#. I'm having a problem in the labels that blink to show the pattern. When one label is required to blink twice (because it appears in the pattern twice) it will only blink once. Also, in general the labels will sometimes not blink in the correct order they are meant to (i.e the second in the pattern blinks before the first). Any assistance in how to fix this or in general how to improve on my code would be great. I have only been using C# for the last few weeks and it's part of a university project.
Have attached the code and a picture of what the windows form looks like.
Windows Form
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Simon2
{
public partial class Form1 : Form
{
List<int> sequence = new List<int>();
Random rnd = new Random();
int number = 0;
public Form1()
{
InitializeComponent();
sequence.Add(rnd.Next(0, 4));
hey();
}
void hey()
{
foreach (int colour in sequence)
{
switch (colour)
{
case 0: {
timer1.Enabled = true;
break;
}
case 1: {
timer2.Enabled = true;
break;
}
case 2: {
timer3.Enabled = true;
break;
}
case 3: {
timer4.Enabled = true;
break;
}
}
}
}
void pattern(int colour)
{
if (sequence[number] == colour)
{
label1.Text = ("Score: " + sequence.Count);
sequence.Add(rnd.Next(0, 4));
number = 0;
hey();
}
else
{
MessageBox.Show("Fail!");
Application.Exit();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (Red1.BackColor == Color.Transparent)
{
Red1.BackColor = Color.Red;
timer1.Interval = 300;
}
else
{
Red1.BackColor = Color.Transparent;
timer1.Interval = 300;
timer1.Stop();
}
}
private void timer2_Tick(object sender, EventArgs e)
{
if (Blue1.BackColor == Color.Transparent)
{
Blue1.BackColor = Color.Blue;
timer2.Interval = 300;
}
else
{
Blue1.BackColor = Color.Transparent;
timer2.Interval = 300;
timer2.Stop();
}
}
private void timer3_Tick(object sender, EventArgs e)
{
if (Yellow1.BackColor == Color.Transparent)
{
Yellow1.BackColor = Color.Yellow;
timer3.Interval = 300;
}
else
{
Yellow1.BackColor = Color.Transparent;
timer3.Interval = 300;
timer3.Stop();
}
}
private void timer4_Tick(object sender, EventArgs e)
{
if (Green1.BackColor == Color.Transparent)
{
Green1.BackColor = Color.Lime;
timer4.Interval = 300;
}
else
{
Green1.BackColor = Color.Transparent;
timer4.Interval = 300;
timer4.Stop();
}
}
private void Red_Click(object sender, EventArgs e)
{
pattern(0);
}
private void Blue_Click(object sender, EventArgs e)
{
pattern(1);
}
private void Yellow_Click(object sender, EventArgs e)
{
pattern(2);
}
private void Green_Click(object sender, EventArgs e)
{
pattern(3);
}
}
}
I am not familiar with the game itself, my understanding is that one light after the other has to light up.
My suggestion: Use Thread.sleep (UI will not be responsive while this does it's thing), instead of timers, directly in the switch:
switch (colour){
case 0: {
Red1.BackColor = Color.Red;
Thread.Sleep(500);
Red1.BackColor = Color.Transparent;
break;
}
edit:
a better way would be to use a while loop which checks if a certain amount of ms elapsed and put Application.DoEvents(); in there

How can I delete all Panels from my calendar?

I'm programming an calendar with C# right now.
If i call my calendar, it creates as much panels as the current month has days. But if I want to increase the current month by one, the panels from the current month are stilt there.
So i have to delete all my panels as soon as I change the month.
But how can i do it in this case ?
Thanks for the help.
Code eplain:
First I call the createPanel method, to create panels for the current month.
Next if I click the MonthAdd method, I want to delete all my created panels.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Globalization;
namespace Einteilungs_Plan
{
public partial class Kalender : Form
{
public DateTime TodayDate { get; set; }
int counting = 0;
public Kalender()
{
InitializeComponent();
//Kalenderwochen initialisieren
monat(counting);
createPanel(true);
}
public string monat(int adding)
{
string monat = DateTime.Now.AddMonths(adding).ToString("MMMM");
tbMonat.Text = monat;
return monat;
}
private void btnAddMonth_Click(object sender, EventArgs e)
{
counting++;
if(counting < 12)
{
monat(counting);
switch (counting)
{
case 0:
int number = 10;
break;
case 1:
break;
default:
break;
}
}
else
{
counting--;
}
}
private void btnRemoveMonth_Click(object sender, EventArgs e)
{
counting--;
if (counting > -1)
{
monat(counting);
}
else
{
counting++;
}
}
public void createPanel(bool remove)
{
var numDays = DateTime.DaysInMonth(DateTime.Today.Year, DateTime.Today.Month);
int locationX = 12;
int locationY = 74;
for (int i = 0; i <= numDays; i++)
{
//Create Panel
Panel test = new Panel();
//Fill Panel
test.Name = "panel" + i;
test.Width = 200;
test.Height = 100;
test.BackColor = Color.White;
test.Location = new System.Drawing.Point(locationX, locationY);
this.Controls.Add(test);
test.Show();
if(i == 6 || i == 13 || i == 20 || i == 28)
{
locationY += 106;
locationX = -194;
}
locationX += 206;
}
}
public void Kalender_Shown(object sender, EventArgs e)
{
}
private void Kalender_Load(object sender, EventArgs e)
{
}
private void btnNeuerEintrag_Click(object sender, EventArgs e)
{
Formular formular = new Formular();
formular.Show();
formular.Focus();
}
private void btnHinzufügen_Click(object sender, EventArgs e)
{
Formular formular = new Formular();
formular.Show();
formular.Focus();
}
}
}
...
for (int i = 0; i <= numDays; i++)
{
//Create Panel
test[i] = new Panel();
}
...
and then
this.Control.Remove(test[i]);
I'm not sure if I undestood you well but first simple solutiona that comes into my mind is that while creating panels you can keep them in some List for example and before generating new month you can call
foreach (var p in panels)
this.Controls.Remove(p);

Read Serial Port on C# allocating on an array no forgetting "00"

I'm trying to do a program that reads a serie of data from a serial port (COM3). The problem is that my code is for example (in decimal):
170 85 01 128 01 129 46 00 00 00 00 00 05 46
The way I'm reading the bytes "00" aren't been allocated on the array or variable:
I try a lot of ways like:
await port.BaseStream.ReadAsync(buffer, 0, 1);
And like shows on microsoft web site:
using System;
using System.IO.Ports;
class PortDataReceived
{
public static void Main()
{
SerialPort mySerialPort = new SerialPort("COM1");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.Open();
Console.WriteLine("Press any key to continue...");
Console.WriteLine();
Console.ReadKey();
mySerialPort.Close();
}
private static void DataReceivedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}
}
But all this methods doesn't work.
Does any one knows any way from get this data and allocate in an array?
How about something to investigate what's happening? If you start a new Winforms project with a single form, a button (buttonStart), and six text boxes, and then put this code behind it
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
int RxRead;
int n;
public Form1()
{
InitializeComponent();
}
private void buttonStart_Click(object sender, EventArgs e)
{
serialPort1.PortName = "COM3";
serialPort1.BaudRate = 9600;
serialPort1.Open();
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
for (n = 0; n < 23; n++)
{
if (serialPort1.BytesToRead > 0)
{
RxRead = serialPort1.ReadByte();
if (n == 0)
{
textBox1.AppendText(RxRead.ToString());
}
if (n == 1)
{
textBox2.AppendText(RxRead.ToString());
}
if (n == 2)
{
textBox3.AppendText(RxRead.ToString());
}
if (n == 3)
{
textBox4.AppendText(RxRead.ToString());
}
if (n == 4)
{
textBox5.AppendText(RxRead.ToString());
}
if (n == 5)
{
textBox6.AppendText(RxRead.ToString());
}
if (n == 6)
{
serialPort1.Close();
}
}
}
}
}
}
Then I would hope that, when you press the start button, you will get the first six bytes displayed in the text boxes. This would let you see whether the 00 bytes are actually being read at all, or whether they are being discarded for some reason? I haven't got a serial port hooked up on my machine, so my apologies if there are any errors in the code.
Cheers,
Nick
If it's any help, here is a program that I wrote a long while back to pick up data coming in over a serial port from two sensors. It's very clunky programming, but as I recall it did (mostly!) work, so there may be something you can use.
Cheers,
Nick
[][1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace serial_port_with_events_attempt_4
{
public partial class Form1 : Form
{
string RxString;
int RxRead;
int i;
int j;
int RxDec1;
int RxDec2;
int RxDec3;
float RxFloat;
float RxFloat2;
string locnString = "Unknown";
DateTime deleteDate;
string deleteDateString;
string testString;
public Form1()
{
InitializeComponent();
deleteDate = DateTime.Today;
deleteDate = deleteDate.AddDays(-7);
deleteDateString = deleteDate.ToString();
textBox1.AppendText(deleteDateString);
}
private void buttonStart_Click(object sender, EventArgs e)
{
serialPort1.PortName = "COM8";
serialPort1.BaudRate = 9600;
serialPort1.Open();
if (serialPort1.IsOpen)
{
buttonStart.Enabled = false;
buttonStop.Enabled = true;
//textBox1.ReadOnly = false;
}
}
private void buttonStop_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
buttonStart.Enabled = true;
buttonStop.Enabled = false;
//textBox1.ReadOnly = true;
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
for (j = 0; j<23 ; j++)
{
if (serialPort1.BytesToRead > 0)
{
RxRead = serialPort1.ReadByte();
this.Invoke(new EventHandler(DisplayText));
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
}
private void DisplayText(object sender, EventArgs e)
{
if (RxRead == 126)
{
//textBox1.AppendText(Environment.NewLine);
i = 0;
}
if (i< 23)
{
if (i == 13)
{
testString = RxRead.ToString();
textBox1.AppendText(testString);
if (RxRead == 82) // 82 in this position means that the temp sensor is the low range one (R1L)
{
//textBox1.AppendText("Temperature in Nick's office = ");
locnString = ("Nicks office");
}
if (RxRead == 195) // 195 in this position means that the temp sensor is the high range one (R1H)
{
//textBox1.AppendText("Temperature in Nick's office = ");
locnString = ("Sitting Room");
}
}
if (i == 17)
{
RxDec1 = RxRead - 48; // Read the tens unit
}
if (i == 18)
{
RxDec2 = RxRead - 48; // Read the units
}
if (i == 20)
{
RxDec3 = RxRead - 49; // read the decimal
}
if (i == 22)
{
RxFloat = ((RxDec1 * 10) + RxDec2);
RxFloat2 = RxDec3;
RxFloat2 = RxFloat2 / 10;
RxFloat = RxFloat + RxFloat2;
// Frig about to get the reads in the right format and added together
RxString = RxFloat.ToString();
if (RxFloat < 30 && RxFloat >10)
{
//textBox1.AppendText(RxString);
if (locnString == "Nicks office")
{
button1.Text = RxString;
}
if (locnString == "Sitting Room")
{
button2.Text = RxString;
}
// Put the value in the main text box if it is not corrupt, (checking if the range is reasonable
temperature1DataSetTableAdapters.Temp1TableAdapter temp1tableadapter = new temperature1DataSetTableAdapters.Temp1TableAdapter();
temp1tableadapter.Insert(DateTime.Now, RxFloat, locnString);
// Add a new line into the temperature database
}
deleteDate = DateTime.Today;
deleteDate = deleteDate.AddDays(-7);
deleteDateString = deleteDate.ToString();
textBox1.Clear();
textBox1.AppendText(deleteDateString);
temperature1DataSetTableAdapters.TempTableAdapter temp2tableadapter = new temperature1DataSetTableAdapters.TempTableAdapter();
temp2tableadapter.DeleteTempQuery(deleteDate);
//textBox1.AppendText("BreakpointA");
textBox1.AppendText(testString);
// Delete any old data.
// TODO Doesn't seem to be working. Don't understand why not. The code gets to here as Breakpoint A gets triggered
this.tempTableAdapter.Fill(this.temperature1DataSet.Temp);
chart1.DataBind();
// These two lines refresh the chart. Took me a long time to figure this out. Basically, you have to
// rerun the query and then run the DataBind method to update the chart control.
// Good article on table adapters http://msdn.microsoft.com/en-us/library/bz9tthwx%28VS.80%29.aspx
//** test code for second chart.
this.tempSensor2AdapterTableAdapter.tempSensor2Fill(this.temperature1DataSet.tempSensor2Adapter);
chart2.DataBind();
}
}
i=i+1;
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'temperature1DataSet.tempSensor2Adapter' table. You can move, or remove it, as needed.
this.tempSensor2AdapterTableAdapter.tempSensor2Fill(this.temperature1DataSet.tempSensor2Adapter);
// TODO: This line of code loads data into the 'temperature1DataSet.Temp' table. You can move, or remove it, as needed.
this.tempTableAdapter.Fill(this.temperature1DataSet.Temp);
chart2.ChartAreas[0].AxisX.LabelStyle.Format = "{0:dd/MM H:mm}";
chart1.ChartAreas[0].AxisX.LabelStyle.Format = "{0:dd/MM H:mm}";
}
}
}

Timer intervals, Making 1 timer stop another timer -

Hey guys im trying to get a simple button masher up, What i want timer1 to do is mash keys in richtextbox1 for 30 seconds over and over, after 30 seconds Activate timer2, which will disable timer 1 and press keys in richtextbox 2 once, then wait 10 seconds and activate timer 1 again.
Im extremley new to c# but ive tried using timer 3 to stop timer 2 and start timer 1 again and it just messes it self up. The code ive tried is below. Any help apreciated...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
SendKeys.Send(richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
timer2.Enabled = true;
}
private void timer2_Tick(object sender, EventArgs e)
{
SendKeys.Send(richTextBox2.Text);
SendKeys.Send("{ENTER}");
timer1.Enabled = false;
}
private void timer3_Tick(object sender, EventArgs e)
{
timer1.Enabled = true;
timer2.Enabled = false;
}
private void richTextBox2_TextChanged(object sender, EventArgs e)
{
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
I suggest to use just one timer, increment a state counter every second, and perform an action base on the current state.
public Form1()
{
this.InitializeComponent();
// Just to illustrate - can be done in the designer.
this.timer.Interval = 1000; // One second.
this.timer.Enable = true;
}
private Int32 state = 0;
private void timer_Tick(Object sender, EventArgs e)
{
if ((0 <= this.state) && (this.state < 30)) // Hit text box 1 30 times.
{
SendKeys.Send(this.richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
else if (this.state == 30) // Hit text box 2 once.
{
SendKeys.Send(this.richTextBox2.Text);
SendKeys.Send("{ENTER}");
}
else if ((31 <= this.state) && (this.state < 40)) // Do nothing 9 times.
{
// Do nothing.
}
else
{
throw new InvalidOperationException(); // Unexpected state.
}
// Update state.
this.state = (this.state + 1) % 40;
}
The variant with two numeric up down controls.
public Form1()
{
this.InitializeComponent();
// Just to illustrate - can be done in the designer.
this.timer.Interval = 1000; // One second.
this.timer.Enable = true;
}
private Int32 state = 0;
private void timer_Tick(Object sender, EventArgs e)
{
Decimal n1 = this.numericUpDown1.Value;
Decimal n2 = this.numericUpDown2.Value;
if ((0 <= this.state) && (this.state < n1))
{
SendKeys.Send(this.richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
else if (this.state == n1)
{
SendKeys.Send(this.richTextBox2.Text);
SendKeys.Send("{ENTER}");
}
else if ((n1 <= this.state) && (this.state < n1 + n2))
{
// Do nothing.
}
else
{
// Reset state to resolve race conditions.
this.state = 0;
}
// Update state.
this.state = (this.state + 1) % (n1 + n2);
}
If timer3 is running continuously, won't it start timer1 and stop timer2 at unpredictable times, without warning?
IOW, what starts and stops timer3?
As JustLoren pointed out, there might be a cleaner way to do this. Perhaps a single timer event and some controlling logic and flags, rather than trying to juggle three timers.

Categories

Resources