NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » CPU/GPU Temp Monitor

July 23, 2010
by ioScream
ioScream's Avatar

I've decided to move this discussion to here, because where I am at is beyond the scope of the original post.

What I have is the MCU setup to display my temperatures on the LCD screen from my monitoring software on my PC.

Basic run-down is: LCD <- MCU <- Python <- Monitoring software

Right now I have the Python script able to grab the values from shared memory, but the problem is that the values are in DWORD. Anyone have any ideas on how to get this to readable, sendable, parsable text?

I keep thinking I'm in over my head with the programming, but in a night I've managed to learn python enough to open a socket, send usable data (test figures) to the MCU, and access shared memory from my monitoring software. Though, I'm reading that Python doesn't have a native library for dealing with DWORD.. and I really don't want to add another program to this party. That was the main reason for learning how to access shared memory. Maybe I need to use ctype? If anyone is interested in helping me and would like to see what I'm dealing with I have a file I can email/upload.

July 23, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi ioScream,

Can you point us to the monitoring program you are planning to use. I still have a feeling there should be a better way of doing this than mucking around in shared memory, but maybe there isn't and you are on the right track. The fact that you are getting data out is pretty neat though.

DWORD is really just a data type, so you will probably have to find a way to make sense of it in Python before sending it over to the MCU. It seems like this will require figuring out how your monitoring program stores its data.

If you post up what you have, I would be glad to take a look at it. It seems like a neat project.

Humberto

July 23, 2010
by ioScream
ioScream's Avatar

I'm using Rivatuner available at Guru3d.com. As far as I know, the SDK files aren't available separate from the install. However, I might be able to zip up the files and upload them somewhere.

The program does allow file logging, but with limitations with my intended use. First being that it stops logging after the file reaches a certain size (mostly for bench-marking purposes), which leads into my next "issue" with using that method. I really don't want to have to do deal with a 10meg (or greater depending on Polling intervals and length of time I want to run it) file and then further parse the information down to just the values.

You seem pretty hesitant with messing with the shared memory, however the portion of shared memory I am accessing stores ONLY the values of each component configured, and is INTENDED (as far as I can see) to be read by other programs such as vista/7 widgets/gadgets.

I imagine there could be some problems using this method, however I am accessing it for read-only, and not modifying it in anyway.. also accessing it via it's "symbolic" name which is referenced in the visual cpp sample file I referred to.

July 23, 2010
by ioScream
ioScream's Avatar

http://www.titeroofs.com/test/new.txt

Here is the data I am getting from shared memory. As you can see it exactly everything I need, nothing more. Just need to understand the DWORD data-type a little better, and how to implement it into Python to keep this a one-script job.

July 23, 2010
by ioScream
ioScream's Avatar

Sorry for the multiple posts, but this is what "know" about the file: The first set of information APPEARS to be an identification header (version number included??) Next is the device it is reading, followed by the unit of measurement, then the temperature. There is also additional flags that says if that component's status is being shown as a tool-tip, OSD, and/or on the icon.

July 23, 2010
by ioScream
ioScream's Avatar

Looking over it again it appears to be a combination of LPByte and DWORD.. of course the final step is the hardest.

July 25, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi ioScream,

I cannot seem to be able to find just the documentation for the SDK without installing the software. Sorry I can't be of more help there. I am hesitant about reading from shared memory spaces because I would just consider it poor software practice, and I would have expected there to be some other more straightforward way of reading the data. However if that is the way this program is meant to expose the data to plugins, then it is fine to try to use it.

It looks like you are going on the right track though. Is there somewhere in the documentation that you can point us to, or link us to so we can see if we can help decode the data you have?

Humberto

July 25, 2010
by ioScream
ioScream's Avatar

There are a few lines of code that are of particular interest:

This is from the .h file

typedef struct RTHM_SHARED_MEMORY_HEADER
{
    DWORD   dwSignature;
        //signature allows applications to verify status of shared memory

        //The signature can be set to:
        //'RTHM'    - hardware monitoring memory is initialized and contains 
        //          valid data 
        //0xDEAD    - hardware monitoring memory is marked for deallocation and
        //          no longer contain valid data
        //otherwise the memory is not initialized
    DWORD   dwVersion;
        //header version ((major<<16) + minor)
        //must be set to 0x00010001 or greater to use this structure
    DWORD   dwNumEntries;
        //number of subsequent RTHM_SHARED_MEMORY_ENTRY entries
    time_t  time;
        //last polling time
    DWORD   dwEntrySize;
        //size of entries in subsequent RTHM_SHARED_MEMORY_ENTRY entries array
} RTHM_SHARED_MEMORY_HEADER, *LPRTHM_SHARED_MEMORY_HEADER;
/////////////////////////////////////////////////////////////////////////////
#define RTHM_SHARED_MEMORY_ENTRY_FLAG_SHOW_IN_TOOLTIP               0x00000001
#define RTHM_SHARED_MEMORY_ENTRY_FLAG_SHOW_IN_ICON                  0x00000002
#define RTHM_SHARED_MEMORY_ENTRY_FLAG_SHOW_IN_OSD                   0x00000004
/////////////////////////////////////////////////////////////////////////////
// v1.1+ entry structure (array of entries follows immediately by the header)
typedef struct RTHM_SHARED_MEMORY_ENTRY
{
    char    czSrc[32];
        //data source name (e.g. "Core temperature")
    char    czDim[16];
        //data source dimansion (e.g. "°C")
    float   data;
        //last polled data in raw format (e.g. 50°C)
        //(this field can be set to FLT_MAX if data is not available)

        //take a note that the user can enable raw data transforming mode and
        //display different values on the graph (e.g. raw core VID values can
        //be translated to mapped core voltages).
        //In this case you may use dataTransformed field to get transformed value
    float   offset;
        //user specified data offset (e.g. +10°C temerature compensation)

        //take a note that this value is not automatically added to transformed
        //data, it is up to you to add offset to it
    float   dataTransformed;
        //last polled data in transformed format
    DWORD   flags;
        //bitmask, containing combination of RTHM_SHARED_MEMORY_ENTRY_FLAG_... flags
} RTHM_SHARED_MEMORY_ENTRY, *LPRTHM_SHARED_MEMORY_ENTRY;
/////////////////////////////////////////////////////////////////////////////
#endif //_RTHM_SHARED_MEMORY_INCLUDED_

//////////-------------------------------------------------\\\\\\\\

it reads the header here and sets up the display -- i've copied it down to where it formats the final display

if (lpHeaderV10->dwSignature == 'RTHM')
            //check if we're connected to valid memory
        {
            CTime time(lpHeaderV10->time);
            CString strBuf = time.Format("%d-%m-%Y %H:%M:%S");
                //format data polling time

            DWORD dwSources = lpHeaderV10->dwNumEntries;
                //get number of data sources

            m_strStatus.Format("Connected to RTHM shared memory v%d.%d\n\n%d data source(s) have been polled on %s\n\n", lpHeaderV10->dwVersion>>16, lpHeaderV10->dwVersion & 0xffff, dwSources, strBuf);

            for (DWORD dwSource=0; dwSource<dwSources; dwSource++)
                //display info for each data source
            {
                if (lpHeaderV10->dwVersion == 0x10000)
                    //we must use special handling code for shared memory v1.0, because entry size field (which is 
                    //reuiqred for unified access to entries) was added to header in v1.1 only
                {
                    LPRTHM_SHARED_MEMORY_ENTRY_V_1_0 lpEntry = (LPRTHM_SHARED_MEMORY_ENTRY_V_1_0)((LPBYTE)(lpHeaderV10 + 1) + dwSource * sizeof(RTHM_SHARED_MEMORY_ENTRY_V_1_0));
                        //get ptr to  the current data source's entry

                    //display data source's info

                    if (lpEntry->data == FLT_MAX)
                        strBuf.Format("%-32s\t : N/A\n", lpEntry->czSrc);
                    else
                        strBuf.Format("%-32s\t : %.1f %s\n", lpEntry->czSrc, lpEntry->data, lpEntry->czDim);
                }
                else
                {
                    LPRTHM_SHARED_MEMORY_HEADER lpHeader    = (LPRTHM_SHARED_MEMORY_HEADER)m_pMapAddr;
                    LPRTHM_SHARED_MEMORY_ENTRY  lpEntry     = (LPRTHM_SHARED_MEMORY_ENTRY)((LPBYTE)(lpHeader + 1) + dwSource * lpHeader->dwEntrySize);
                        //get ptr to the current data source's entry

                    CString strSrc;

                    //display data source's info

                    if (lpEntry->offset == 0.0f)
                        strSrc = lpEntry->czSrc;
                    else
                        strSrc.Format("%s (%+.1f)", lpEntry->czSrc, lpEntry->offset);

                    if (lpEntry->data == FLT_MAX)
                        strBuf.Format("%-32s\t : N/A", lpEntry->czSrc);
                    else
                        /*

                                THIS BEGINS MY HACK AND SLASH JOB

                        */
                        //My Comments -- All is well and this is what is displayed
                        strBuf.Format("%-32s\t : %.1f %s", strSrc, lpEntry->dataTransformed + lpEntry->offset, lpEntry->czDim);
July 25, 2010
by ioScream
ioScream's Avatar

If anyone needs definitions or declaration lines let me know.. they are easy to find in Visual CPP.. i just don't understand enough of it to get it to display properly.. still working on it though.

July 25, 2010
by ioScream
ioScream's Avatar

While it was cool to access memory with python, I've decided to use an output file with the existing cpp code that I will read with python for now.. I would LOVE to find out how to handle these data-types with Python so I only need 1 file to run, but for now I have a working solution.

Hopefully, someoen can shed some light on this subject or maybe I'll figure it out later. Maybe I'll even update the cpp program further to have IT read to the LCD.

July 27, 2010
by ioScream
ioScream's Avatar

Well, I've managed to get this project at a working state. It now reads all my PC temps (4 cores/GPU) gpu fan-speed, and it's duty cycle (ex: 50%). With a push of the momentary switch the display changes to the current time and date information. Another push shows the up-time (currently at about 12 hours, no glitches), and a final push will cycle you around to the temperature readings. I plan to add CPU/GPU loads, as well as, available/used memory. I would like to figure out how some of the gaming LCD's read health/ammo from games, and when I do I will add that functionality.

I think the next phase of this project is to make it more "scalable", so that when I want to make changes on what is to be displayed I don't have to reprogram the MCU. I'm considering adding a web-interface, or maybe use Python to create a windowed environment (GUI). I'll be trying to stay with Python for the entire project as this is the language that the nerdkit guys use, and I will be releasing the code for anyone to view so it can run parallel with the projects that are available.

If anyone has suggestions or ideas please let me know.

July 28, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi oiScream,

I would love to see pictures of the working project. It sounds really neat.

Humberto

Post a Reply

Please log in to post a reply.

Did you know that hobby servos are controlled through a particular kind of PWM (Pulse Width Modulation) signal? Learn more...