Reading ADC from C

Moderators: TomKerekes, dynomotion

Post Reply
katiefangffs
Posts: 14
Joined: Sat Feb 17, 2024 9:57 am

Reading ADC from C

Post by katiefangffs » Tue Mar 19, 2024 9:50 am

Hi!

I'm working on reading a temperature value from ADC channel 0.
Previously, I directly read it using KMotion and displayed it on the CNC screen by saving the variable as a DRO label. However, due to user requests, I now need to rewrite the code to read the value through Visual Studio, which will run in the background as the KMotionCNC app is loaded by the user, and update the temperature on the screen as well. I've read a few articles about "MainStatus" and the ".NET" namespace, but I'm still a bit confused about how to make this work.

I have a few questions:

1. I'm including the "Mainform.cs" file as a resource in my .sln file. In this case, do I still need to include header files like "Kmotiondef.h" and "PC-DSP.h"?
2. If I'm running this in Visual Studio, do I still save the variable to DRO labels to upload it onto the CNC UI, or do I use another function?
3. When creating the Visual Studio project, I'm currently selecting "Windows Forms App (.NET Framework)". Is this a good option? Also, does it matter if I run it in either C# or C++?

If there is any code snippet for similar projects that can be provided that would be great.

Thank you! Sorry for so many questions. I appreciate your help!

p.s. This is my old code that works fine:

Code: Select all

#include "KMotionDef.h"
#define TMP 10
#include "KflopToKMotionCNCFunctions.c"
// Function to read from ADC and convert to temperature
void readtemp() {
    // Access the ADC channel for Kogna ADCs
    int adc_value = Kogna_ADC_Buffer[0]; 

    // Use the provided macro to convert ADC value to voltage
    float voltage = KOGNA_CONVERT_ADC_TO_VOLTS(adc_value);

    // Convert voltage reading to temperature
    float temp_range = 100.0 - 0.0;
    float voltage_range = 5 - 0.0;
    float temp = ((voltage - 0.0) / voltage_range) * temp_range + 0.0;
    char s[80];
  
    sprintf(s,"%.2f °C\n", temp);
   
	
	DROLabel(1000, 162, s);
    // Print results
    printf("The ADC reading is %d, which corresponds to a voltage of %.2f V.\n", adc_value, voltage);
    printf("This voltage corresponds to a temperature of %.2f °C.\n", temp);
}

int main() {
    double nextTime = Time_sec(); // Initialize nextTime to the current time

    while (1) { // Infinite loop to continuously read temperature
        nextTime += 2.0; //read every 2 sec
        readtemp(); 
        WaitUntil(nextTime); 
    }

    return 0;
}




Attachments
KM_MainStatus.cs
(40.12 KiB) Downloaded 166 times

katiefangffs
Posts: 14
Joined: Sat Feb 17, 2024 9:57 am

Re: Reading ADC from C

Post by katiefangffs » Tue Mar 19, 2024 4:45 pm

Update: I found this sln file: "KMotion5.3.1\PC VC Examples\BuildExamples\BuildExamples.sln". Should I build something like this that include all the functionalities I want to include in C++? (I have a few other variables to be updated as well and also some bits to be read)

User avatar
TomKerekes
Posts: 2676
Joined: Mon Dec 04, 2017 1:49 am

Re: Reading ADC from C

Post by TomKerekes » Tue Mar 19, 2024 5:51 pm

Hi Katie,

The C Function in KFLOP:

Code: Select all

	DROLabel(1000, 162, s);
Puts a character string at offset 1000 into KFLOP's Gather Buffer. Then sets KFLOP Persist variable 162 to 1000 to indicate a string is available.

KMotionCNC polls KFLOP persist variable 162 for a non-zero value and if non-zero uses the value as an index into KFLOP's Gather Buffer and uploads a block of data from that offset in the Gather Buffer as the string and then displays the string.

If you wish to do this from your App you would need to do the same thing that the KMotionCNC App does.

The KM_MainStatus record has all the axis data an IO bits and such but doesn't contain data that you would need to display string messages.

The BuildExamples.sln is a collection of many example projects. I'd suggest that you use C# and our .NET interface which is a very easy interface to our Libraries. SimpleForms is a good example for you to look at.

To read a persist variable from KFLOP you can use the GetUserData function.

SimpleFormsCS has a Test USB/Ethernet button that downloads a large block of data to KFLOP's Gather Buffer and then Uploads it. You can use that example to see how to upload data from KFLOP's Gather Buffer. Its a bit complex as the data is uploaded as 32-bit hexadecimal words where the characters need to be converted to binary 32-bit words.

HTH. Let us know how much of this you understand.
Regards,

Tom Kerekes
Dynomotion, Inc.

katiefangffs
Posts: 14
Joined: Sat Feb 17, 2024 9:57 am

Re: Reading ADC from C

Post by katiefangffs » Wed Mar 20, 2024 10:39 am

Hi,
Using this code, I can now read the correct ADC value using C# and converted it into the accurate temperature. Following that, I sent a "setpersist" command to the console script to assign the temperature value to a persistent variable. I tested this by sending the "getpersist" function in the console and verified that the variable was correctly saved with the accurate value.

However, I encountered an issue when I tried to assign the variable to the DROLabel within the KMotionCNC screen editor. After setting it, the persistent variable in the code no longer gets updated and gets zeroed out. I'm wondering if this could be related to the timer function, like having conflict with both the script and the editor attempting to read the variable simultaneously, or if there's a mistake in how I'm using any of the functions.

Code: Select all

using System;
using System.Windows.Forms;
using KMotion_dotNet;
using System.Diagnostics; // For debug

namespace temp0320
{
    public partial class Form1 : Form
    {
        KM_Controller KM;
        int skip = 0; // Initialize skip counter
        bool Connected = false; // Track connection status

        public Form1()
        {
            InitializeComponent();
            KM = new KM_Controller(); // Initialize KM_Controller
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Setup and start a timer for continuous operation
            Timer timer = new Timer();
            timer.Interval = 1000; // Every 1000 milliseconds (1 second)
            timer.Tick += timer1_Tick;
            timer.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (!Connected || skip++ > 20)
            {
                skip = 0;
                // Attempt to connect or check connection here
                Connected = CheckConnection(); 
            }

            if (Connected)
            {
                FetchADCValue(); // Fetch and process ADC value when connected
            }
            else
            {
                Debug.WriteLine("Not connected or waiting to retry.");
            }

   
        }

        public void FetchADCValue()
        {
            try
            {
                if (KM.WaitToken(100) == KMOTION_TOKEN.KMOTION_LOCKED)
                {
                    var status = KM.GetStatus(false); // Get current status from the controller
                    short adcValue = status.Kogna_ADC[0]; //ADC channel 0
                    float temperature = ConvertADCToTemperature(adcValue); // Convert ADC to temperature

                    // Debug output
                    Debug.WriteLine($"ADC Channel 0 Value: {adcValue}, Temperature: {temperature:F2} °C");
                    
                    string command = $"SetPersistDec 11 {temperature}";
                    KM.WriteLine(command); // Send the command to set the persist variable

                    KM.ReleaseToken();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error: {ex.Message}");
                KM.ReleaseToken();
            }
        }


        private float ConvertADCToTemperature(int adcValue)
        {
            // Conversion
            float voltage = (float)adcValue * (6.144f / 2047.0f);
            float tempRange = 100.0f - 0.0f;
            float voltageRange = 5.0f - 0.0f;
            float temp = ((voltage - 0.0f) / voltageRange) * tempRange + 0.0f;
            return temp;
        }

        private bool CheckConnection()
        {
            //check the connection...to be written
            return true;
        }
    }
}

User avatar
TomKerekes
Posts: 2676
Joined: Mon Dec 04, 2017 1:49 am

Re: Reading ADC from C

Post by TomKerekes » Wed Mar 20, 2024 5:36 pm

Hi Katie,

I don't understand the point of what you are trying to do. The PC C# App reads the ADC from KFLOP, converts it to Temperature, then writes the Temperature to KFLOP persist variable 11. KFLOP could easily do this calculation without using the PC.

So you are expecting the persist variable 11 value to be displayed in KMotionCNC DROLabel? What code do you have in KFLOP to do this? KMotionCNC is expecting a string of characters to display in the DROLabel.

There might also be a persist variable conflict as:

Code: Select all

#define TMP 10 // which spare persist to use to transfer data
#include "KflopToKMotionCNCFunctions.c"
can use several persist variables starting at 10
Regards,

Tom Kerekes
Dynomotion, Inc.

Post Reply