I want to feed my Arduino with an AC signal (level shifted if necessary) and read that signal in a self made C# Windows application.
I already made the C# Windows application earlier in this Github repository.
For an AC signal I will use my signal generator.
Question 1: What voltage range is acceptable for an Ardunio's GPIO pin? 0-5 V, as shown on this page. Also to keep in mind is the maximum current which appears to be 40 mA according to this page. I will use a 10k╬®├┐ current limiting resistor.
The board I am using is an Arduino Nano v3.0 (possibly a clone since the Arduino logo is missing). I have to select the 'ATmega 328P (old bootloader)' to write code to it.

I used the default code from the 'Read Analog Voltage' example that comes with the Arduino IDE:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
Serial.println(voltage);
}Then I wrote a small Windows Forms application in C#. Note that the MSChart library is used. Also the form has a ChartRefreshTimer Timer which I set to 200 ms. The separate thread reads values from serial as fast as it can but the UI is updated only once in a while.
Download a zip with the Visual Studio project here.
using System;
using System.Globalization;
using System.IO.Ports;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace TestRealtimeChart2 {
public partial class Form1 : Form {
// Array that holds the values.
internal static double[] values;
// To keep track of where the latest value was written in the array.
internal static int currentValueIndex;
// How many values to keep before starting from the beginning.
internal const int MAX_VALUE_COUNT = 1000;
public Form1() {
InitializeComponent();
// Set the correct culture so a dot is parsed as a decimal point.
CultureInfo customCulture = (CultureInfo) Thread.CurrentThread.CurrentCulture.Clone();
customCulture.NumberFormat.NumberDecimalSeparator = ".";
Thread.CurrentThread.CurrentCulture = customCulture;
// Start a new thread so the UI does not freeze.
Thread thread1 = new Thread(ReadValues);
thread1.Start();
// Initialise the array with the necessary amount of spaces.
values = new double[MAX_VALUE_COUNT];
// Make the Y-axis pretty.
chart1.ChartAreas[0].AxisX.Minimum = 0;
chart1.ChartAreas[0].AxisX.Maximum = MAX_VALUE_COUNT;
}
private void ReadValues() {
// Initialize the COM port.
SerialPort serialPort = new SerialPort("COM5");
serialPort.Open();
while (true) {
// Read a value from serial.
// A Try is used because serial provides gibberish at the start.
double.TryParse(serialPort.ReadLine(), out double currentValue);
// Save the value at the correct spot in the array.
values[currentValueIndex] = currentValue;
// Set the index to the next spot.
currentValueIndex++;
// If at the end, start from the beginning.
if (currentValueIndex >= MAX_VALUE_COUNT) {
currentValueIndex = 0;
}
}
}
private void ChartRefreshTimer_Tick(object sender, EventArgs e) {
// Empty the chart.
chart1.Series[0].Points.Clear();
// Stop the UI from updating the chart for a moment.
chart1.Series[0].Points.SuspendUpdates();
// Add the entire array as points.
for (int i = 0; i < values.Length; i++) {
if (i == currentValueIndex) {
// This point marks the newest read value and is styled differently.
DataPoint point = new DataPoint(i, values[i]);
point.MarkerStyle = MarkerStyle.Circle;
point.MarkerSize = 10;
chart1.Series[0].Points.Add(point);
} else {
chart1.Series[0].Points.AddXY(i, values[i]);
}
}
// Allow the UI to update the chart again.
chart1.Series[0].Points.ResumeUpdates();
}
}
}Result with my AWG set to a sinewave 0-5 V at 1 Hz:

Result with my AWG set to a sinewave 0-5 V at 10 Hz:

Ideas and notes for later: