RC2014 PS/2 keyboard board

There are some new USB keyboards, that behave like a ps/2 keyboard, using the old protocol, if the data+, and the data- lines are pulled up. I have one of these.

I start the board doing the circuit for a 6502 cpu proposed by Ben Eater in the following video, but in the middle I of the process i found the ps/2 keyboard schematic for a z80 available in the cpuville website.

The software for a 6502 is described in the following video (i did not follow the software video).

Then I decide to do a mix from both circuits, and my own view of the enable output logic for the shift registers. From the Ben Eater I retain the interrupt generation, and the inverter on the clock.

cpuville ps/2 keyboard interface

From cpuville I use the interaction concept. One port for reading LSB, and reset the shift registers, and another por to reading the MSB. I also use the main clock to update the output register of the shifters, instead the signal used as interrupt, and invert the data.

RC2014 PS/2 keyboard interface

The circuit was build in a breadboard, and some software was done to check if it is working good.

dav

Software used in tests:

https://github.com/inaciose/asm80/blob/main/test/ps2ktest2.z80

https://github.com/inaciose/asm80/blob/main/test/ps2ktest3.z80

The interface seems to work good. Need to improve the software, and later try include it in the small computer monitor.

https://techdocs.altium.com/display/FPGA/PS2+Keyboard+Scan+Codes

https://wiki.osdev.org/PS/2_Keyboard

ACIA 6551A on Z80

Como usar o IC 6551A (ACIA) como interface serie no z80.

Alguma informação sobre o calculo das resistencias pull up e pull down a usar na serie 74LSxxx, os calculos também se aplicam para outras series 74YYxxx, adequando a corrente e os níveis lógicos de tensão.

https://www.electronics-tutorials.ws/logic/pull-up-resistor.html

Datasheet do IC UM6551A

Circuito da placa serial IO (6551A) para o Z80 com o bus RC2014

Esquema de ligação

Ligações dos pinos do IC6551A

GND – GND

CS0 < not(IOREQ_L) and M1 and A3

CS1_L < A2

RST_L < RESET_L

RxC – not connected

XTAL1 < 1.8432MHz clock signal

XTAL2 < not connected

RTS_L > not connected

CTS_L < GND

TxD > TX out

DTR_L > not connected

RxD < RX in

RS0 < A0

RS1 < A1

VCC – VCC

DCD_L < GND

DSR_L < GND

DB0, DB7 – D0, D7

IRQ_L > INT_L

PHI2 < not(RD_L) or not(WR_L) ) and not(IOREQ_L)

R/W_L < WR_L

Algumas notas sobre a ligação do PHI2. Inicialmente, v1 do circuito, tinha ligado o PHI2 directamente ao clock do Z80. O sistema funcionava mas tinha sempre a transmissão de 3 caracteres em vez de 1.

O problema é que como é visível na imagem Z80 – IO timing, existem 3 ciclos de relógio, enquanto que na imagem UM6551 – Timing, é visível que o 6551 espera um único pulso. Por isso passei a usar os sinais RD_L e WR_L, em conjunto com o IOREQ_L, para formar o sinal de entrada em PHI2.

not(RD_L) or not(WR_L) ) and not(IOREQ_L)

Z80 – IO timing

UM6551 – Timing

O circuito de teste foi implementado numa breadboard

Breadboard acia 6551A for z80 circuit test

Programa em z80 assembly que faz uso do circuito como porta serie e que implementa um echo do receive no transmit

            .ORG    0000 

STACKS      EQU     0xFFFF 
ACIA_DATA   EQU     0x08 
ACIA_STAT   EQU     0x09 
ACIA_CMD    EQU     0x0A 
ACIA_CTL    EQU     0x0B 



MAIN:                

; set stack pointer
            LD      SP,STACKS 


; test io ports
            LD      a,0x01 
            OUT     (0x00),a 
            IN      a,(0x00) 
            OUT     (0x00),a 
            LD      a,0xFF 
            OUT     (0x00),a 
            LD      a,0x00 
            OUT     (0x00),a 
            NOP      

; acia 6551 init

            LD      a,%00000000 ;software reset
            OUT     (ACIA_CMD),a 
            LD      a,%00001011 ;no parity, no echo, no interrupt
            OUT     (ACIA_CMD),a 
            LD      a,%00011111 ;1 stop bit, 8 data bits, 19200 baud
            OUT     (ACIA_CTL),a 

;JP      OLDTEST
HELLO:               
            LD      a,$68 
            CALL    OUTCHAR 
            LD      a,$65 
            CALL    OUTCHAR 
            LD      a,$6C 
            CALL    OUTCHAR 
            LD      a,$6C 
            CALL    OUTCHAR 
            LD      a,$6F 
            CALL    OUTCHAR 
            LD      a,$0A 
            CALL    OUTCHAR 
            LD      a,$0D 
            CALL    OUTCHAR 
            
            ;JP      HELLO

LOOP:                

            CALL    INCHAR
            ;a char is received
            LD      c, b
            LD      b,%00001000 
            AND     b 
            JP      nz,INC_IDLE
            ; yes get received char
            LD      a, c
            CALL    OUTCHAR 
            
INC_IDLE:
            ; no received char

            JP      LOOP 


;
; OUTCHAR 
; arguments
; a = char to output
;
OUTCHAR:             
            LD      c,a
OUTCHART:
            ; check transmit flag is set
            LD      b,%00010000 ; 
            IN      a,(ACIA_STAT) 
            ;OUT     ($00),a         ;show stat on leds
            AND     b 
            JP      z,OUTCHART 
            ; send char
            LD      a,c 
            OUT     (ACIA_DATA),a 
            RET      
;
; OUTCHAR 
; arguments
; a = char to output
;
INCHAR:              
            LD      c,$00 
            ; check receiv flag is set
            LD      b,%00001000
            IN      a,(ACIA_STAT) 
            ;OUT     ($00),a         ;show stat on leds
            AND     b 
            JP      z,INCHAR_ 
            ; read receive register
            IN      a,(ACIA_DATA) 
            LD      c,a 
            LD      b,$00 
INCHAR_:    
            ; no received char
            LD      a,b 
            LD      b,c 
            RET      


ACIA6551_STATUS:             
; led show FF
            LD      a,$FF 
            OUT     ($00),a 

; show cmd reg
            IN      a,(ACIA_CMD) 
            OUT     ($00),a 

; show ctl reg
            IN      a,(ACIA_CTL) 
            OUT     ($00),a 

; show stat reg
            IN      a,(ACIA_STAT) 
            OUT     ($00),a 
      
            JP      loop 

Alguns recursos consultados para desenvolver o port do acia 6551 serial IO para o z80.

UM6551A

https://www.grappendorf.net/projects/6502-home-computer/acia-serial-interface-hello-world.html

ACIA 6551

https://www.atarimagazines.com/compute/issue10/075_1_EXPERIMENTING_WITH_THE_6551_ACIA.php

Homebrew 6502 : 6551 UART issues

https://github.com/ancientcomputing/rc2014/tree/master/source/6502/monitor

https://github.com/transitorykris/krisos/tree/master/io

Fazer um PCB numa CNC 3018 – Candle

Depois de obter os ficheiros gcode com o isolamento e a furação é hora de os usar para fabricar o pcb na cnc 3018.

O processo de fabricação consta das seguintes grandes fases: a passagem de isolamento e a passagem de furação. Ambas necessitam de preparação, e entre elas temos que trocar a ferramenta (do vbit para a broca).

Depois de abrir o Candle, os passos são os seguintes:

  • File > Open, abrir o ficheiro nc da passagem de isolação das pistas.
  • Colocar a ponta (tool) na origem do PCB (canto mais próximo esquerdo).
  • Clicar em Zero XY. (Definir o zero,zero do sistema de eixos. Cresce para a direita e para o fundo)
  • Colocar os jacarés no PCB e na Tool.

Heightmap preparation

  • Colocar a ponta +/- a 3 mm de distancia ao PCB
  • Clicar em Zero Z (probe) (acertar o zero Z)
  • Clicar no botão Heightmap > Create
  • Clicar no botão Heightmap > Auto (definir tamanho do pcb)
  • Verificar o probe grid (Zb deve ser um valor adequado ao home do Z de forma a que possa encontrar o PCB até esse valor. O X e o Y devem ser um numero de vezes que permita 10mm entre cada ponto da grelha.
  • Clicar no botão Probe (na zona do programa), (assegurar que os jacarés estão ligados), (a maquina começa a fazer as medições, quando parar passamos ao ponto seguinte)
  • File > Save, nome do ficheiro (incluir .map)
  • Clicar no botão Heightmap > Edit (Para sair do modo create.)
  • Colocar o visto em Use heightmap

Enviar o ficheiro gcode e iniciar a execução

  • Remover o jacaré do tool
  • Clicar no botão Send (na zona do programa).
  • O Tool mexe-se e pára (o status fica amarelo a dizer Hold), e temos que clicar no botão Pause para continuar.
  • A fabricação começa

A fase da prefuração

  • File > Open, abrir o ficheiro nc correspondente a furação
  • Aumentar um bocado a distancia do tool ao PCB (usar setas)
  • Mudar de ferramenta (trocar o vbit por uma broca)
  • Colocar o jacare no tool (temos que voltar a acertar o zero Z com um Z probe)
  • Mover o tool para o 0,0 (usar setas)
  • Clicar no botão Heightmap > Open, e selecionar o ficheiro.map gerado anteriormente
  • Colocar um visto em Use heightmap
  • Clicar no botão Zero Z (probe) (assegurar que os jacarés estão ligados)

Enviar o ficheiro gcode e iniciar a execução

  • Remover o jacaré do tool
  • Clicar no botão Send (na zona do programa).
  • O Tool mexe-se e pára (o status fica amarelo a dizer Hold), e temos que clicar no botão Pause para continuar.
  • O processo de furação começa

Z80 – circuito de teste

Comprei uns z80 no ali e pesquisei na net por um circuito de teste para o ic z80. Procurei na web por circuito s de teste e encontrei um vários, alguns deles descritos em video, do qual seleccionei o video abaixo, onde é feita uma breve apresentação do circuito. Outra fonte que tomei que usei foi a informação disponivel em http://www.z80.info/z80test0.htm.

Com base nessas duas fontes montei numa breadboard um circuito de teste do z80 e notei que o ic do z80 não encaixava bem na breadboard.

Entretanto recebi um socket zif 40 pinos, e como gostava de fazer também um circuito para testar cpus 6502, resolvi fazer uma pequena placa perfurada para encaixar zif numa socket de ic de 40 pinos, e ligadas a 20 pinos de cada lado da placa.

dav

Resolvi então dividir a coisa em 3 placas diferentes,

  • uma para gera o relógio, com base num ic 555.
  • uma que encaixa-se nos pinos 21 ao 40,
  • uma que encaixa-se dos pinos 1 ao 20

Efectuei a do relógio, e a que se encaixa nos pinos 21 e 40. Entretanto desisti da outra placa, porque já tinha passado muito tempo no assunto.

dav

A parte correspondente aos pinos 1 a 21 foi montada em breadbord, e foi tudo ligado. ficou uma confusão de fios. Mas aparentemente o circuito funcionou como esperado. Com os leds a piscarem conforme sugerido no video. Na imagem abaixo está a saída capturada pelo logic analyzer.

Outro site com informação Z80 Test Circuit

Entretanto abandonei a ideia de fazer a placa para os pinos 1 a 20.

Regresso aos braços robóticos

O problema encontrado nas experiências de pick & place com o braço robótico eezyBotArm mk2 (ebamk2), associado à falta de motivação para encontrar uma alternativa a esse braço, a que se juntou ainda o tempo ocupado a estudar matemática, coincidiu com o abandono dos meus projectos na área da robótica.

Além do ebamk2, também fiz uma versão nele baseada mas com motores de passo em vez de servo motores, o RobotArm mk2 plus (ramk2p), que nunca explorei tanto quanto o anterior.

Quer um braço quer outro, são de 3dof, e com o desaire das experiências pick & place com o ebamk2, deixei de lado a exploração do ramk2p.

Comecei então a germinar a ideia de fazer um braço robótico de 6dof e a direcção inicial foi começar por usar de novo servo motores. Mas desisti em grande medida pela observação de alguns vídeos de projectos deste tipo nos quais os braços exibiam um comportamento instável e que se afastam da precisão que queria.


Roboticarm V1

O braço robótico no video acima, tem apenas 5 DOF e como ainda imprimi a maior parte das peças também verifiquei que algumas das peças não permitem um bom funcionamento sem modificações. Face a mais este desaire (em particular a falta de estabilidade) passei para outra ideia.

Nesta fase a minha ideia passou a ser um braço robótico de 6DOF impresso em 3D e baseado em motores de passo, cujo projecto estivesse disponível na web, fosse relativamente preciso. fácil de fazer, e económico.

Ao longo do tempo elaborei uma lista de braços robóticos que é possível montar com recurso a peças de feitas em impressora 3D e outros componentes que tem de ser necessariamente comprados. Por exemplo rolamentos e motores. Mas essa lista revela que os meus critérios não são satisfeitos por nenhum dos projectos. Todos os que tem um bom grau de precisão são complicados e caros.

Por outro lado também reparei que não existe nenhum braço robótico baseado em motores de passo fácil de construir e que não custe umas centenas de euros.

Provavelmente o braço robótico que se pode construir num projecto caseiro que mais se aproxima da simplicidade e custo relativamente reduzido (menos de 350 euro) é o thor.

A informação mais actualizada do projecto do braço robótico thor está disponível no seguinte endereço:

https://github.com/AngelLM/Thor

Para além do repositório no github o thor tem também informação disponível no thingiverse e no hackaday.

Ainda assim, sendo simples, este braço tem na sua lista de materiais uma serie de componentes que não tenho disponíveis, alguns deles caros, como os motores de passo com caixas redutoras.

Também considerei desenhar um braço robótico por mim próprio, e cheguei a comprar algumas correias e rolamentos para os usar num projecto desses.

Neste momento, diria que cheguei a um impasse. Se bem que queira desenhar, eu próprio, um braço robótico simples e económico, creio que me faltam algumas competências para o fazer.

Um problema de orientação

O problema com o pick and place com o moveit, e da execução do posicionamento do end effector conforme o tutorial do moveit foi no minimo mitigado, quando não resolvido.

Quando descobri o uArm (swift e pro), mais um braço do tipo do eezybotarm, e o software que estes braços têm para o ros moveit disponivel no github, e verifiquei que com este software o moveit conseguia efectuar o planeamento. Após rápida reflexão a razão do sucesso parecia evidente. O urdf destes braços não incluia em nenhuma joint mimic.

A descrição que efectuei do ebamk2 incluia duas mimic joints. Uma entre o link_2 e um link virtual que acrescentei entre este e o link_3, para descrever a relação que existe entre o movimento destes links, pois não são complementamente independentes. Outra entre o link_3 e o link_4, que é o link final onde se connecta o end effector. Estes dois links relacionam-se atravez de duas articulações, a que estabelecem entre si, e a que o link 4 estabelece com uma articulação passiva no corpo do braço, cujo objectivo é manter o end effector sempre horizontal.

Portanto, rescrevi o urdf do eezybotarm mk2 de duas formas, uma sem nenhuma joint mimic, e outra em que conservei a joint mimic e o link virtual entre o link_2 e o link_3, e quando experimentei acabei por ter sucesso no passo em que estava encalhado no tutorial do moveit (mover o braço robótico para um pose).

Ou seja, a orientação do end effector na versão com o mimic entre a joint_3 e joint_4 era impossivel de atingir, pois era incompativel com o quaternion (x,y,z,w) com os valores (0,0,0,1).

eezybotarm mk2 pick and place problem

The eezybotarm mk2 pick and place problem is about the lack of DOF

As minhas experiências falhadas com o pick and place no eezybotarm mk2 derivaram da incapacidade de fazer o planner do moveit fazer a cinemática inversa do braço robótico, pois o braço tem apenas 3DOF e parece que é necessário 6DOF.

Ainda não digeri completamente esta incapacidade, pois no rviz com o Allow Aproximate IK Solutions activo, é possivel movimentar e calcular a trajectória para a pose, mas no script de pick and place é impossivel, mesmo que a posse seja muito aproximada a pose actual e portanto possivel.

Procurei encontrar uma forma de activar o Allow Aproximate IK Solutions no programa de pick and place em python e fui conduzido para o seguinte método, mas sem sucesso.

move_group.set_joint_value_target(pose_goal, self.eef_link, True)

Também descobri dois novos ik solvers:

  • track_ik – http://wiki.ros.org/trac_ik
  • bio_ik – https://github.com/TAMS-Group/bio_ik

Dos dois apenas experimentei e passei a usar o bio_ik, que foi facil de instalar.

É muito provavel que desista de explorar o eezybotarm mk2 no ros moveit, pelo menos temporariamente, e tentar fazer um braço com os 6DOF para voltar a este assunto do pick and place.

Ros moveit GripperCommand

Mais um problema resolvido. Como descobri que não tenho nenhuma interface visual para interagir com o gripper no moveit rviz, não está completamente conforme com a minha ideia inicial. Mas é o melhor que consegui descobrir por enquanto.

Mais tarde acho que irei dedicar um bocado de atenção ao moveit_grasps, mas por enquanto o proximo passo é descobrir como funciona o pick and place.

The quest for a robot with moveit follow joint trajectory

Após conseguir fazer a cinemática inversa para o eezybotarm mk2 no moveit, e conduzir o robot em espelho com a apresentação do rviz, por subscrição do fake_controller_joint_states, quando se corre o demo.launch, andei em busca da integração com o moveit! com base nas mensagens follow joint trajectory.

Na minha humilde perspectiva, de quem não teve qualquer formação de relevo para o assunto, devo dizer que provavelmente para quem não sabe, há assuntos que parece muito difícil encontrar informação sobre o eles.

O controlo de movimentos de um braço robótico físico com o ros moveit parece uma delas. O que eu diria é que não existe nenhum exemplo para a exploração de um braço físico de baixo custo com o moveit!

Existe informação, ambiguidades, questões sobre a implementação que por vezes não sabemos como colocar, e portanto até pesquisar, e algumas questões respondidas. Regra geral a solução está numa dessas respostas. Até mesmo quando por vezes temos alguma ideia conceptual de como a coisa funciona, ficamos imenso tempo a procura de alguns detalhes que são fundamentais.

Entretanto parece que consegui encontrar todos os pequenos detalhes para colocar a funcionar a integração do braço eezybotarm mk2 com o ros moveit, sem recorrer a soluções menos apropriadas como as que tinha ensaiado anteriormente. Ainda assim acho que não estou a usar ainda um hardware interface ao estilo do ros control.