Closed Sarxell closed 2 years ago
Hi @miguelriemoliveira, @vitoruapt
De momento é necessária a adquisição do material necessário para esta solução:
Codificadores incrementais: O nosso encoder tem as seguintes especificações pela tese do Tiago Rocha: https://ie.rs-online.com/web/p/motion-control-sensors/2603718
Na RS: Este da RS parece-me parecido apenas é um bocado maior, apresenta 40mm de diâmetro do corpo (está em espanhol portanto deve ser isso) 8.KIS40.1342.1000 | Encoder incremental Kubler serie KIS40, 1000 impulsos/rev, salida Pulsar Tirar, 10 → 30 V dc, IP64 | RS Components (rs-online.com) (134€) Usa um cabo com 6 sinais em vez de 3 como o anterior Este da sick DBS36E-S3EK01000 | Encoder incremental Sick serie DBS36 Core, 1000 impulsos/rev, 8000rpm máx., salida HTL, con Cable, 7 → 30 V., | RS Components (rs-online.com) (105€) Usa 6 sinais em vez de 3 como o anterior
Na Mouser: Só encontrei codificadores caros todos fora de stock.
Na Mauser: Só vendem codificadores muito pequenos.
Na farnell: RE30E-1000-213-1 - Nidec Copal Electronics - Rotary Encoder, Optical, Incremental (farnell.com) este têm uma tensão máxima de 12V mas visto que se quer utilizar a caixa de 12V é possível (88,56 €) , usa 3 sinais O motor do @vitoruapt https://pt.farnell.com/hengstler/ri32-0-1000er-14kb/encoder-rotary/dp/615985
É o que encontrei de momento! Falei com o Engenheiro Rui mas ele não sabe de momento se está um codificador no LAR ou não, terá de se procurar.
Arduino com barramento CAN:
Opção igual á tese do Diogo Figueiredo ( CAN-BUS shield + Arduino UNO) -> o Engenheiro Rui disse que esta solução deverá estar no LAR portanto poderá ser utilizada Utilizar um CANBed (Arduino CAN-BUS Development Kit (ATmega32U4 with MCP2515 and MCP2551)) -> teria de se comprar +/- 20-30€ O Luís Cristovão utilizou o MCP2515 com o raspberry pi2 model B, visto que um raspberry não é necessário as duas soluções acima são melhores
Cabos OBD <-->DB9: Os cabos do @vitoruapt os quais parecem-me os melhores: https://www.amazon.es/-/pt/dp/B081N7G2BR/ref=sr_1_1?crid=Y2B3MC7TI81G&keywords=cable+cable+obd+db9&qid=1650973385&quartzVehicle=881-85&replacementKeywords=cable+cable+obd&sprefix=can+cable+obd+db9%2Caps%2C122&sr=8-1 E a extensão: https://www.amazon.es/dp/B07KF9LHMF/ref=twister_B07KG78937?_encoding=UTF8&th=1
Na electrofun existe um cabo maior mas não sei se esse comprimento seria suficiente na mesma logo os da amazon serão mesmo a melhor escolha tal como devem chegar mais rápido Cabo OBD-II DB9 (electrofun.pt) comprimento de 1.52m
Vai ser criada posteriormente uma mensagem custom CAN:
Na página 51 da tese, o Diogo Figueiredo fala que criou mensagens custom para o barramento CA. Em lars.mec.ua.pt/public/LAR Projects/HardwareInterfaces/2020_DiogoFigueiredo/ArduinoCode/send_pedal/send_pedal.ino pode-se ver o código que ele escreveu no qual envia para o id 0x500, portanto essa parte parece – me simples de criar.
Hi @vitoruapt and @miguelriemoliveira ,
Right now the encoder is already purchased
We found in LAR Diogo Figueiredo solution of the CAN-Bus shield and a obd <--> db9 cable
I already tested it and made it send the values to the CAN Bus as well as read from it .
I think right now it's only wait to get the encoder and install it
Right now the encoder is already purchased ? What do you mean? Is it ordered already? Did you talk to Eng. Rui?
You mean ordered... right?
Yes I talked to him and sent him the encoder via email. He said he was going to ordered it in the afternoon
Yes, sorry
Hello! @Sarxell and I have progressed. The old encoder support was disassembled, making it ready for the new one. Two new pieces need to be fabricated.
One of them is a replacement for this part, because the new encoder's shaft is 1 mm smaller than the old one. The model is done, I will post the drawing here ASAP.
The other one is the piece that connects the encoder support to the wheel. The part will be something like this (the 40 mm hole in the middle will be removed).
We partially tested this support using a 3DP printed part:
Once the technical drawings are updated, I will post them here.
@miguelriemoliveira and @vitoruapt, what do you think? With your approval, I can ask Eng. Festas to start production of these.
Hi @manuelgitgomes ,
from my side please advance. Let's see what @vitoruapt says.
Hi @miguelriemoliveira and @vitoruapt,
I already created an Arduino code to count the encoder pulses and calculate the speed and other code to send the value via CAN-Bus message. Now I want to fuse these two codes but I have a problem.
For example: If the car is moving at 75km/h which gives 20.83333 m/s, my first idea was to use 2 bytes, where 20 <- byte 1 and 833 < - byte 0
This is not possible since the max byte value is 255! To use this idea I could only get to centimeters (83)...
What do the professors think? Should I think about a formula to send the values easier? Use 3 bytes? Or is this value enough?
Hi @Sarxell ,
I remember @vitoruapt said we had four bytes available?
Why not send the speed in millimeters per second using four bytes?
Four bytes in a signed variable (assuming we also want know we are moving backwards) has a maximum value of (2^32)/2 = 2147483647 millimeters per second.
Let's say we're moving at 100 Km / hour, that's (100 1000 1000) millimeters / (60*60) secs = 27777,7 millimeters per second
27777,7 is well below the max of 2147483647 so we should be fine ... not sure if this is the best way ...
I thought you wanted displacement only, not speed, but anyway, the question is the same. There are several possibilities. For velocity you could use dm/s that would give 208.33 dm/s, but if you go faster than 25.5 m/s (255 dm/s) you fall into the same problem! Moreover, that is not the recommenced way to represent numbers. You should think of an integrated way using two bytes: with two bytes you can go up to 65535, or 0xFFFF. If that number represents mm/s you can go up to very fast velocities for our car (65 m/s ~ 234 km/h). So, just decompose the speed in mm/s into two bytes and send the message with two bytes: the MSB and the LSB.
However, in the Arduino program you must store your encoder value that at 1000 pulses/turn gives you 1000 pulses/1.5m, that is, about 670 pulses per meter. So if you travel at 20 m/s, that gives you more than 13000 pulses/s. Hopefully, the Arduino will not miss any pulse... :-)
Nonetheless, 670 pulses/meter will generate 67 million pulses in a 100 km ride, that is, you need ~26 bits. So, you will need between 3 and 4 bytes to store and transmitt that information in our setup. For example, if you wan to publish the state of the encoder in the CAN bus, for our local rides, 3 bytes seems enough, but you can go up to 4 bytes if you need (that would allow rides of about 6410 km!).
One last thing. You need also to count backwards, and if you start in zero, going backwards gives a negative number. When transmitting negative numbers in digital format you can use either one's complement or two's complement. The later is usually preferable but a little more complex. Anyway, check it out and use whatever you prefer... just document it properly ;-)
Okay, I will try that way then!
Hello @vitoruapt and @miguelriemoliveira !
Right now I decided to simulate the wheel from the atlascar2 using a motor with encoder that I had at home!
I created the following circuit:
I still only tested to see if the CAN Bus worked, the negative part is not implemented.
I also changed the python code to receive this ID in the ackermann_drive msg !
Here is just a small video to show the CAN bus and arduino working
Tomorrow I wil improve this code, get the correct value in the python code and transmit negative numbers.
Nice going ;-)
I still only tested to see if the CAN Bus worked, the negative part is not implemented.
If your encoder0Pos
variable in the Arduino is a long signed integer, the counting runs both ways including negative numbers and perhaps you can send the associated 4 bytes to the CAN and when reading them you can insert them into a signed long integer (using a kind of union in C language :-) ) and the transfer to and from CAN bus is automatic... that's only a suggestion, but I am sure you will figure out this or even a better solution :-) !
Hi @vitoruapt and @miguelriemoliveira , Right now I was able to do the negative and positive values , I used this code since looking in the internet It was the solution I was capable to work better with:
byte signed stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop() { //Loop runs forever//
// I will only know if this is right after checking with the wheel encoder
newposition = encoder0Pos;
newtime = millis();
if (newtime - oldtime >= 1000) {
noInterrupts ();
// pulses per second
frequency = (newposition-oldposition) * 1000 /(newtime-oldtime);
RPM = frequency/maxPPR;
// SERIAL_PORT_MONITOR.print ("vel = ");
// SERIAL_PORT_MONITOR.println (RPM);
// get velocity in mm/s
veh_speed =(RPM*PI*wheel_radius)/(30*gear_ratio)*1000;
SERIAL_PORT_MONITOR.print ("vehicle speed = ");
SERIAL_PORT_MONITOR.println (veh_speed);
oldposition = newposition;
oldtime = newtime;
// Send velocity to the CAN Bus
stmp[0] = (veh_speed >> 24);
stmp[1] = (veh_speed >> 16);
stmp[2] = (veh_speed >> 8);
stmp[3] = veh_speed;
long newLong = (stmp[0] << 24) | (stmp[1] << 16) | (stmp[2] << 8) | (stmp[3]);
Serial.println(newLong);
Serial.print(stmp[0],HEX);
Serial.print(" ");
Serial.print(stmp[1],HEX);
Serial.print(" ");
Serial.print(stmp[2],HEX);
Serial.print(" ");
Serial.println(stmp[3],HEX);
CAN.sendMsgBuf(0x501, 0, 8,stmp);
SERIAL_PORT_MONITOR.println("CAN BUS sendMsgBuf ok!");
interrupts ();
}
}
I got the values at 1Hz for the video but also because this motor only has 16PPR, so 100Hz gives imprecise values (it's not really a problem, I only need to change the variables when using the real encoder)
So , I got the following video to check the negative and positive values:
Today I will change the python code to get this value and add it in the ackermann_drive msg
Hi again @miguelriemoliveira and @vitoruapt !
So I discovered that when sending using the lower bytes, in can I received then in the higher ones, like in the photo:
So I changed the code, just traded the array positions which gave me the following results:
The value matches the arduino! Receiving this value in python was quite simple:
if msg.arbitration_id == 0x500:
# speed is in km/h
print(msg.data)
speed_mm = int.from_bytes(msg.data, "big", signed=True)
print(speed_mm)
I would appreciate some feedback, if I need to improve something, etc. The CAN-Bus also has 8 data bytes available and not 4 so if the professors prefer I can use the 8, it is something simple to change.
Fine! Four bytes seems enough for our encoder, so I suppose you can keep it that way! Now we just need to see this in action in the car :-) Maybe in a week or two with all the hardware settled ;-)
Hi @vitoruapt and @miguelriemoliveira ,
We already installed the odometer but we are having some issues... The encoder is always moving foward ! Even when I already tested this code and was working at home. This already happened one time with the motor but I changed the pins on the arduino and it started working again, so I will test this at home with the motor and tomorrow I will test it in the Atlascar2 again.
The other problem can be connected with the above which is "ghost pulses". This pulses happen when the car is stopped and the encoder value continues to increment, this might be due to oscillations. This oscillations might be caused by the lack of a silicone filling in the encoder's enclosure. Although this oscillations are back and forward, due to the precious problem they are all incrementing.
I think it's better to resolve the first problem and then check the second one.
Best regards, Sara
Hi @vitoruapt and @miguelriemoliveira ,
We already installed the odometer but we are having some issues... The encoder is always moving foward ! Even when I already tested this code and was working at home. This already happened one time with the motor but I changed the pins on the arduino and it started working again, so I will test this at home with the motor and tomorrow I will test it in the Atlascar2 again.
That is a good start. Do you have power from the car new switch board? Hope so ! :-) Counting only in one sense must absolutely be solved... see why below!
The other problem can be connected with the above which is "ghost pulses". This pulses happen when the car is stopped and the encoder value continues to increment, this might be due to oscillations. This oscillations might be caused by the lack of a silicone filling in the encoder's enclosure. Although this oscillations are back and forward, due to the precious problem they are all incrementing.
The ghost pulses when the car is stopped would be expected for such a high resolution encoder because vibrations occur naturally. However, that should occur in both directions and, in average, the counting should cancel! So, this is why counting in both directions is absolutely necessary also to annihilate this drift!
I think it's better to resolve the first problem and then check the second one.
Sure.
Nice job!
That is a good start. Do you have power from the car new switch board? Hope so ! :-)
We used a DC voltage supply since the plug for the encoder only arrives tomorrow!
I really don't know what can be causing the error from the counting since when I tested it count back and forward was working with the same code and encoder ... Tomorrow I will test it again
We used a DC voltage supply since the plug for the encoder only arrives tomorrow!
OK, let's hope for the best...
I really don't know what can be causing the error from the counting since when I tested it count back and forward was working with the same code and encoder ... Tomorrow I will test it again
Are you using two different interrupt I/Os for channels A and B or a single interrupt line (along with some extra tricks :-))? Is the Arduino code available in the GitHub repository?
Nice work. Let me know if I can help in some way ...
Is the Arduino code available in the GitHub repository?
It's https://github.com/lardemua/atlascar2/blob/master/atlascar2_description/nodes/Atlascar2_encoder_v2/Atlascar2_encoder_v2.ino! I put it here now :)
I'm only using one of the channels as an interrupt...maybe I need to use both for a more robust solution..
So, changing the resistances from 120ohm to 1k helped , at least it's working at home using the motor and encoder
It's https://github.com/lardemua/atlascar2/blob/master/atlascar2_description/nodes/Atlascar2_encoder_v2/Atlascar2_encoder_v2.ino! I put it here now :)
I cannot find https://github.com/lardemua/atlascar2/blob/master/atlascar2_description/nodes/Atlascar2_encoder_v2
So, changing the resistances from 120ohm to 1k helped , at least it's working at home using the motor and encoder
Where are these resistors connected? Do you have a schematic of the circuit?
I cannot find https://github.com/lardemua/atlascar2/blob/master/atlascar2_description/nodes/Atlascar2_encoder_v2
This link is working for me! It's in the atlascar2_description/nodes
The resistors are connected on the Channel A and channel B of the encoder... I still didn't do the schematic
This link is working for me! Now, I see it. Thanks. It seems that you are not attaching the Arduino timestamp (millis()) in the data sent. Don't you think that it can be useful for more precise measurements instead of counting on the ROS timestamps to assess velocity?
The resistors are connected on the Channel A and channel B of the encoder... I still didn't do the schematic
OK. Don't worry. We will see the schematic later! But why do you need resistors, are you using voltage dividers because of 12 V vs. 5 V, or is there any other reason? Putting low resistors to the ground at the output of some devices can drain too much current and jeopardize the voltage measurements! Where is the other end of the resistors plugged?
Done
Since the CAN values are too imprecise, we can use an incremental encoder to give us better results.