Други технологии > Роботика

Непрецизност на DC мотор - управуван од Raspberry Pi/Arduino

<< < (2/3) > >>

GigaWatt:

--- Quote from: Atanas on 08.03.2019, Friday, 14:17:00 ---Не сфатив што е динамичко кочење?
--- End quote ---

Да дадеш краткотраен „контра“ сигнал ;). Краткотраен негативен импулс, за да застанат тркалата ;).


--- Quote from: Atanas on 08.03.2019, Friday, 14:17:00 ---Инаку ова е возилото од видеото, само што јас му имам наместено и сензор за ротации, како и батерија за напојување на RPi и RF приемник.
--- End quote ---

Вакво нешто му имаш монтирано?

Atanas:
Да, со помош на photo interrupter и тоа ги мерам ротациите на тркалото. И на пример после 10 ротации го запирам возилото итн итн.

EDIT: Ако помогне и ако е од корист, драјверот за моторите што е на плочката од RF приемникот е со ознаки MX1608RX2 1637H.

Atanas:
Еве го и кодот што е за на компјутер, преку кој ги добивам податоците од RPi и испраќам команди до Arduino.


--- Code: ---https://www.dropbox.com/s/qf5ktinnpwwpbzk/server_update.txt?dl=0
--- End code ---


--- Code: ---#include <iostream>
#include <WS2tcpip.h>
#include <string>
#include "SerialPort.h"
#include <chrono>
#include <thread>

#pragma comment (lib, "ws2_32.lib")

using namespace std;

string podatok(char* buf, SOCKET clientSocket)
{
int actualSize = 0;

ZeroMemory(buf, 4096);

int bytesReceived = recv(clientSocket, buf, 4096, 0);

string data = string(buf, 0, bytesReceived);

return data;
}

void forward(char* buf, SOCKET clientSocket)
{
int counter = 0;
//int actualSize = 0;
Serial* SP = new Serial("\\\\.\\COM6");

if (SP->IsConnected())
{
cout << "Forward" << endl;
}

int rotacija = 0;

while (SP->IsConnected())
{
char command[2] = { '*','*' };

command[0] = 'R';
command[1] = 'U';

SP->WriteData(command, 3);

//for (int i = 0; i < 4; i++)
//{
for (;;)
{
{
string data = podatok(buf, clientSocket);

if (data.size() == 1)
{
//cout << "brojac" << endl;
counter++;
std::chrono::duration<int, std::milli> timespan(20);
std:this_thread::sleep_for(timespan);

if (counter == 16)
{
command[1] = '*';
std::chrono::duration<int, std::milli> docnenje(20);
std::this_thread::sleep_for(docnenje);
command[0] = '*';
std::this_thread::sleep_for(docnenje);

SP->WriteData(command, 3);
delete SP;
break;
}
cout << counter << endl;
}
}
//cout << "J >> " << j << endl;
}
break;
//}
//break;
}
}

void main()
{
// Initialze winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);

int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
cerr << "Can't Initialize winsock! Quitting" << endl;
return;
}

// Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
cerr << "Can't create a socket! Quitting" << endl;
return;
}

// Bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; // Could also use inet_pton ....

::bind(listening, (sockaddr*)&hint, sizeof(hint));

// Tell Winsock the socket is for listening
listen(listening, SOMAXCONN);

// Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);

SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);

char host[NI_MAXHOST]; // Client's remote name
char service[NI_MAXSERV]; // Service (i.e. port) the client is connect on

ZeroMemory(host, NI_MAXHOST); // same as memset(host, 0, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);

if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
cout << host << " connected on port " << service << endl;
}
else
{
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
cout << host << " connected on port " <<
ntohs(client.sin_port) << endl;
}

// Close listening socket
closesocket(listening);

// While loop: accept and echo message back to client
char buf[4096];
char name[4096];


forward(buf, clientSocket);


// Close the socket
closesocket(clientSocket);

// Cleanup winsock
WSACleanup();

system("pause");
}
--- End code ---

Да објаснам на кратко што се случува... Со функцијата getdata() ги добивам податоците од клиентот, односно RPi. Во функцијата forward() во while loop ја повикувам функцијата getdata() преку која што земам податоци од RPi, тие со во тип на податок string. Потоа, имам if (data.size() == 1)  со кој што проверувам дали сензорот вратил 1, тоа значи дека неговата состојба е на една од празнините на тоа тркалцето што го заокружи Giga во претходниот пост. На тоа тркалце има такви 20 дупчиња, што по логика би требало на секои 20 вратени 1, да има изминато една ротација. Но, тоа тука не функционира така, не знам од која причина. Со условот if (counter == 30) кажувам додека бројачот не достигне вредност 30 да се испраќаат команди до количето, а кога ќе се достигне да се исклучат моторите - тука може да стои било која вредност, оваа е само за тестирање. Тоа го правам со:


--- Code: ---command[0] = '*';
command[1] = '*';
SP->WriteData(command, 3);
--- End code ---

Каде што во Arduino кодот е напишано кога ќе се добијат овие ѕвездички моторите да престанат. Тоа е накратко за кодот ако не е доволно јасно, кажете ќе дообјаснам.

Во меѓувреме, бидејќи имам 2 вакви шасии за количе, од едната шасија моторите ги ставив на оваа шасија од видеото и проблемот се корегира т.е количето оди право, но кога ќе дадам команда да вози наназад тоа се искрувува малце. Се сомневам дека е до задното помошно тркало, тоа што е за држење правец. Мислења?

tanatos:
Со таков распоред на тркала неможеш да возиш назад. Слободното тркало на секоја нерамнина ќе менува насока бидејќи е туркано. Кога возилото се движи во другиот правец нема таков проблем.

GigaWatt:
Си пробал да дебагираш? Линија по линија да извршуваш, да видиш каде е проблемот и дали ќе се јави проблемот ако извршуваш линија по линија... бидејќи можно е и да е real world проблем, не софтверски (како што пиша tanatos, да не е инерција во прашање).

Притоа, чисто совет, кога ќе го извршуваш loop-от, број си во себе колку пати е извршен ;). Ако треба да е 20, да е навистина 20 ;).

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version