No edit summary |
|||
(6 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Wer brauchte nicht | Wer brauchte nicht schon immer einen einfachen Drehzahlmesser, hatte aber keinen zur Hand. Hier beschreibe ich eine Möglichkeit mittels einer einfachen PC-Maus mit Scrollrad. Ich wollte die Drehzahl von zwei Gleichstrommotoren erfassen die ich im Rahmen eines Balancierenden Roboter (Prinzip des inversen Pendels) einsetzen wollte. | ||
einfachen PC-Maus mit Scrollrad. | Die Gleichstrommotoren hatte ich mit einen PWM-Signal und einer kleinen Treiberschaltung angesteuert. Hinter jedem Motor befand sich ein dahintergschaltetes Getriebe. | ||
Ich habe beide Motoren mit dem selben PWM-Signal angeseteuert aber es kam mir so vor, dass diese sich unterschiedlich schnell drehten. Nur ohne Drehzahlmesser ist das schwer nachzuweisen. Dann kam mir die Idee die Drehzahl mit dem Scrollrad einer Maus zu erfassen. Dafür habe ich ein kleines Programm geschreiben das ihr im Download-Bereich der Artikels findet. Quelltext ist auch verfügbar und kann nach belieben erweitert werden. Über die Genauigkeit kann ich nichts sagen, da ich keinen Drehzahlmesser für Vergleichsmessungen besitze. | |||
== Benutzung == | |||
[[File:MouseScrollCounter.jpg|400px|thumb|right]] | |||
Einfach das Programm starten und am Scrollrad drehen. | Einfach das Programm starten und am Scrollrad drehen. Um das Program zu beenden die Linke und Rechte Maustaste gedrückt halten. | ||
== Quelltext == | == Quelltext == | ||
Zu dem Quelltext gibt es nicht allzuviel zu erzählen. | |||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
/*********************************************** | /*********************************************** | ||
Line 48: | Line 53: | ||
LRESULT CALLBACK LowLevelMouseProc(int code, WPARAM wParam, LPARAM lParam) | LRESULT CALLBACK LowLevelMouseProc(int code, WPARAM wParam, LPARAM lParam) | ||
{ | { | ||
if(code == HC_ACTION) | |||
{ | { | ||
const char *msg; | |||
char msg_buff[128]; | char msg_buff[128]; | ||
switch(wParam) | switch(wParam) | ||
{ | { | ||
case WM_LBUTTONDOWN: | |||
msg = "WM_LBUTTONDOWN"; | |||
break; | |||
case WM_LBUTTONUP: | case WM_LBUTTONUP: | ||
msg = "WM_LBUTTONUP"; | |||
break; | |||
case WM_MOUSEMOVE: | case WM_MOUSEMOVE: | ||
msg = "WM_MOUSEMOVE"; | |||
break; | |||
case WM_MOUSEWHEEL: | case WM_MOUSEWHEEL: | ||
msg = "WM_MOUSEWHEEL"; | |||
counts++; | |||
break; | |||
case WM_RBUTTONDOWN: | case WM_RBUTTONDOWN: | ||
msg = "WM_RBUTTONDOWN"; | |||
break; | |||
case WM_RBUTTONUP: | case WM_RBUTTONUP: | ||
msg = "WM_RBUTTONUP"; | |||
break; | |||
default: | default: | ||
sprintf(msg_buff, "Unknown msg: %u", wParam); | sprintf(msg_buff, "Unknown msg: %u", wParam); | ||
msg = msg_buff; | msg = msg_buff; | ||
break; | |||
} | } | ||
Line 123: | Line 128: | ||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||
{ | { | ||
int n = 0; | |||
int rpm = 0; | |||
int rps = 0; | |||
float speed = 0.0; | |||
char buffer[64]; | |||
DWORD startTime = 0; | |||
DWORD diffTime = 0; | |||
// remove scrollbar | |||
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); // get handle of console window | HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); // get handle of console window | ||
CONSOLE_SCREEN_BUFFER_INFO info; | CONSOLE_SCREEN_BUFFER_INFO info; | ||
Line 144: | Line 149: | ||
SetConsoleScreenBufferSize(handle, new_size); // set new size | SetConsoleScreenBufferSize(handle, new_size); // set new size | ||
SetConsoleTitle("DefCon - MouseScrollCounter"); // set title | |||
g_evExit = CreateEvent(0, TRUE, FALSE, 0); | |||
if(!g_evExit) | |||
{ | { | ||
cerr << "CreateEvent failed, le = " << GetLastError() << endl; | cerr << "CreateEvent failed, le = " << GetLastError() << endl; | ||
Line 179: | Line 184: | ||
if(status == (WAIT_OBJECT_0 + 1)) | if(status == (WAIT_OBJECT_0 + 1)) | ||
{ | { | ||
// check if the wheel is reached a revolution | |||
if(counts >= COUNTS_PER_REVOLUTION) | |||
{ | |||
if(startTime != 0) | |||
{ | |||
diffTime = GetTickCount() - startTime; // get time between two calls | |||
} | |||
startTime = GetTickCount(); | |||
if(diffTime != 0) | |||
{ | |||
// get radiation per second and minute | |||
rps = 1000 / (int)(diffTime); | |||
rpm = 60000 / (int)(diffTime); | |||
} | |||
speed = DISTANCE_PER_REVOLUTION * rps; // in m/s | |||
system("cls"); | |||
n = snprintf(buffer, 64, "%c DIFF:%ims --> %i rpm --> %.2f m/s %c", 186, diffTime, rpm, speed, 186); | |||
// ********** draw border ********** | |||
printf("%c", 201); | |||
for(int i = 0; i < n-2; i++) | |||
{ | |||
printf("%c", 205); | |||
} | |||
printf("%c\n", 187); | |||
printf("%s\n", buffer); | |||
printf("%c", 200); | |||
for(int i = 0; i < n-2; i++) | |||
{ | |||
printf("%c", 205); | |||
} | |||
printf("%c\n", 188); | |||
counts = 0; // reset counter | |||
} | |||
continue; // there are messages to process, eat em up | continue; // there are messages to process, eat em up | ||
Line 236: | Line 241: | ||
CloseHandle(g_evExit); | CloseHandle(g_evExit); | ||
return 0; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Download == | == Download == | ||
[ | [[File:MouseScrollCounter.zip]] |
Latest revision as of 20:10, 24 January 2022
Wer brauchte nicht schon immer einen einfachen Drehzahlmesser, hatte aber keinen zur Hand. Hier beschreibe ich eine Möglichkeit mittels einer einfachen PC-Maus mit Scrollrad. Ich wollte die Drehzahl von zwei Gleichstrommotoren erfassen die ich im Rahmen eines Balancierenden Roboter (Prinzip des inversen Pendels) einsetzen wollte. Die Gleichstrommotoren hatte ich mit einen PWM-Signal und einer kleinen Treiberschaltung angesteuert. Hinter jedem Motor befand sich ein dahintergschaltetes Getriebe. Ich habe beide Motoren mit dem selben PWM-Signal angeseteuert aber es kam mir so vor, dass diese sich unterschiedlich schnell drehten. Nur ohne Drehzahlmesser ist das schwer nachzuweisen. Dann kam mir die Idee die Drehzahl mit dem Scrollrad einer Maus zu erfassen. Dafür habe ich ein kleines Programm geschreiben das ihr im Download-Bereich der Artikels findet. Quelltext ist auch verfügbar und kann nach belieben erweitert werden. Über die Genauigkeit kann ich nichts sagen, da ich keinen Drehzahlmesser für Vergleichsmessungen besitze.
Benutzung
Einfach das Programm starten und am Scrollrad drehen. Um das Program zu beenden die Linke und Rechte Maustaste gedrückt halten.
Quelltext
Zu dem Quelltext gibt es nicht allzuviel zu erzählen.
/***********************************************
***
*** eeeeee eeeee eeeee eeeee eeeeee eeeeee
*** 8 8 8 8 8 8 88 8 8
*** 8e 8 8 8 8 8 8 8 8
*** 88 8 8eee 8eee 8e 8 8 8e 8
*** 88 8 8e 8e 88 8 8 88 8
*** 88 e 88 88 88 8 e 88 8
*** 88eee8 88eee 88 88eee 88eee8 88 8
*** ----------------------------------------
*** defcon-cc.dyndns.org
***
************************************************
************************************************
*** Programm: MouseScrollCounter ***
*** Autor: Patrick Langosch ***
*** erstellt: 12.08.14 ***
*** Version: 0.1 ***
***********************************************/
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <windows.h>
#define DIAMETER_WHEEL 0.023 // in meters
#define COUNTS_PER_REVOLUTION 24 // no dimension
#define DISTANCE_PER_REVOLUTION (M_PI * DIAMETER_WHEEL) // in meters
using namespace std;
int counts = 0;
HHOOK g_Hook;
HANDLE g_evExit;
/******************************** LowLevelMouseProc ********************************/
LRESULT CALLBACK LowLevelMouseProc(int code, WPARAM wParam, LPARAM lParam)
{
if(code == HC_ACTION)
{
const char *msg;
char msg_buff[128];
switch(wParam)
{
case WM_LBUTTONDOWN:
msg = "WM_LBUTTONDOWN";
break;
case WM_LBUTTONUP:
msg = "WM_LBUTTONUP";
break;
case WM_MOUSEMOVE:
msg = "WM_MOUSEMOVE";
break;
case WM_MOUSEWHEEL:
msg = "WM_MOUSEWHEEL";
counts++;
break;
case WM_RBUTTONDOWN:
msg = "WM_RBUTTONDOWN";
break;
case WM_RBUTTONUP:
msg = "WM_RBUTTONUP";
break;
default:
sprintf(msg_buff, "Unknown msg: %u", wParam);
msg = msg_buff;
break;
}
const MSLLHOOKSTRUCT *p = reinterpret_cast<const MSLLHOOKSTRUCT*>(lParam);
static bool left_down = false;
static bool right_down = false;
switch(wParam)
{
case WM_LBUTTONDOWN:
left_down = true;
break;
case WM_LBUTTONUP:
left_down = false;
break;
case WM_RBUTTONDOWN:
right_down = true;
break;
case WM_RBUTTONUP:
right_down = false;
break;
}
if(left_down && right_down)
{
SetEvent(g_evExit);
}
}
return CallNextHookEx(g_Hook, code, wParam, lParam);
}
/******************************** MAIN ********************************/
int main(int argc, char *argv[])
{
int n = 0;
int rpm = 0;
int rps = 0;
float speed = 0.0;
char buffer[64];
DWORD startTime = 0;
DWORD diffTime = 0;
// remove scrollbar
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); // get handle of console window
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(handle, &info);
COORD new_size =
{
info.srWindow.Right - info.srWindow.Left + 1,
info.srWindow.Bottom - info.srWindow.Top + 1
};
SetConsoleScreenBufferSize(handle, new_size); // set new size
SetConsoleTitle("DefCon - MouseScrollCounter"); // set title
g_evExit = CreateEvent(0, TRUE, FALSE, 0);
if(!g_evExit)
{
cerr << "CreateEvent failed, le = " << GetLastError() << endl;
return 1;
}
g_Hook = SetWindowsHookEx(WH_MOUSE_LL, &LowLevelMouseProc, GetModuleHandle(0), 0);
if(!g_Hook)
{
cerr << "SetWindowsHookEx() failed, le = " << GetLastError() << endl;
return 1;
}
cout << "Press both left and right mouse buttons to exit..." << endl;
MSG msg;
DWORD status;
/******************************** LOOP ********************************/
while(1)
{
while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
}
status = MsgWaitForMultipleObjects(1, &g_evExit, FALSE, INFINITE, QS_ALLINPUT);
if(status == (WAIT_OBJECT_0 + 1))
{
// check if the wheel is reached a revolution
if(counts >= COUNTS_PER_REVOLUTION)
{
if(startTime != 0)
{
diffTime = GetTickCount() - startTime; // get time between two calls
}
startTime = GetTickCount();
if(diffTime != 0)
{
// get radiation per second and minute
rps = 1000 / (int)(diffTime);
rpm = 60000 / (int)(diffTime);
}
speed = DISTANCE_PER_REVOLUTION * rps; // in m/s
system("cls");
n = snprintf(buffer, 64, "%c DIFF:%ims --> %i rpm --> %.2f m/s %c", 186, diffTime, rpm, speed, 186);
// ********** draw border **********
printf("%c", 201);
for(int i = 0; i < n-2; i++)
{
printf("%c", 205);
}
printf("%c\n", 187);
printf("%s\n", buffer);
printf("%c", 200);
for(int i = 0; i < n-2; i++)
{
printf("%c", 205);
}
printf("%c\n", 188);
counts = 0; // reset counter
}
continue; // there are messages to process, eat em up
}
else
{
break; // assume g_evExit is signaled
}
}
cout << "Exiting..." << endl;
UnhookWindowsHookEx(g_Hook);
CloseHandle(g_evExit);
return 0;
}