FAVORITAR
FecharPlease login

Integrando o barramento CAN ao Android Automotivo 13

Introdução

Os automóveis dessa e da última década são compostos por redes internas, também conhecidas como redes internas do veículo (IVN). As IVNs constroem uma espécie de sistema nervoso interno do carro e são responsáveis pela comunicação entre as diversas unidades de controle eletrônico (ECU) [1].

A Controller Area Network (CAN) é uma rede projetada para permitir que microcontroladores e dispositivos, ou geralmente ECUs se comuniquem entre si sem a necessidade de um computador host. A comunicação ocorre de forma ponto a ponto (P2P). Antes de usar o CAN, cada ECU dos carros eram conectadas através de cabos individuais usando sinais analógicos. O crescente número de ECUs acrescentaram custos e peso adicionais significativos ao carro, o que levou a Bosch desenvolver o padrão CAN em 1986 para apresentar uma solução para este problema. Em 1991, o padrão ISO-11898 foi estabelecido com definição de padrões e conceitos acerca do barramento. Com o CAN, foi possível substituir o sistema antigo, conectando cada componente com apenas uma única linha de dados uniforme na qual os dados são transmitidos sequencialmente [1].

As informações passadas pelo barramento CAN são transmitidas através de dois cabos: CAN High e CAN Low, sem a necessidade de um ground compartilhado, reduzindo drasticamente a quantidade de fios necessários para comunicação. Cada dispositivo conectado a um barramento CAN é chamado de nó. Além disso, normalmente são utilizados resistores de 120 Ω nas extremidades do barramento para reduzir as reflexões de sinal [2]. Para mais informações sobre o CAN e sobre o módulo MCP2515, recomendo a leitura de outro artigo do Embarcados, o Barramento CAN entre Arduinos Uno. Nesse artigo há a explicação mais detalhada do funcionamento do barramento e suas principais características.

O Android Automotive OS (AAOS) estende o sistema Android, adicionando suporte para requisitos, recursos e tecnologias específicas do setor automotivo, bem como a abertura para personalização de sistemas de infoentretenimento automotivo. Além disso, conta com a implementação de uma Camada de Abstração de Hardware (HAL) específica para a comunicação com veículos, a Camada de Abstração de Hardware do Veículo (VHAL) [3]. A interface VHAL define propriedades que os fabricantes podem implementar e preencher com metadados. As propriedades da VHAL são abstrações para funções específicas que podem ser acessadas através de leitura, escrita e assinatura [4]. Para mais informações acerca do AAOS, recomendo a leitura de outro artigo do Embarcados, o Android Embarcado: Compilando e Executando o Android Automotive OS para Raspberry Pi.

Este artigo tem como objetivo integrar a rede CAN e o módulo MCP2515 ao AAOS 13 e a realização de testes da comunicação com o conjunto de ferramentas can-utils. Com essa ferramenta, é possível monitorar o tráfego da rede CAN, enviar mensagens e até gerar um tráfego para testes.

Materiais e pré-requisitos

  • Máquina Linux para desenvolvimento 64 bits, pelo menos 250GB de armazenamento livre e no mínimo 16GB de RAM (o experimento foi desenvolvido utilizando Ubuntu 22.04);
  • Rasberry Pi 4B de 8GB de RAM (para melhor desempenho);
  • Módulo MCP2515 (controlador da rede CAN);
  • Cartão micro SD de no mínimo 16GB para armazenar as imagens;
  • Um display HD com entrada HDMI (pode ser uma tela sensível ao toque também);
  • Um teclado e um mouse (para o caso de displays sem touch);
  • Android Debug Bridge (adb) instalado em sua máquina (Download SDK Platform- Tools for Linux);
  • Ferramenta repo instalada em sua máquina (Instalando Repo);
  • Conhecimento intermediário em uso de terminal Linux;

Será necessário a instalação de alguns pacotes, portanto no Ubuntu 18.04 ou superior, execute o comando:

O Android já vem com os compiladores prebuilt na instalação, porém para evitar erros no momento da compilação, instale o compilador de 64 bits com o seguinte comando:

Baixando os códigos-fontes

Código-fonte do Android Automotivo

Com a ferramenta repo instalada, é necessário configurar o seu usuário e e-mail do git (caso não esteja) com o seguinte comando no terminal:

Para fazer o download dos arquivos de manifest Android 13 utilize a branch android-13.0.0_r52 e execute o comando dentro da pasta criada para o Android:

Para download dos manifest do firmware da Raspberry Pi 4B utilize a branch sa-arpi-13 e execute o seguinte comando dentro da pasta criada:

Uma vez criados os manifests, resta baixar o código-fonte com o comando abaixo:

Ou

A opção -j$(nproc) ajuda a distribuir a execução do comando de acordo com as threads do seu processador. O processo pode levar bastante tempo, caso sua internet caia e gere algum erro, cancele a operação e execute o comando anterior novamente.

Baixando os códigos-fontes do kernel Android

Para realizar o download dos arquivos de manifest do kernel, crie uma pasta e execute o seguinte comando dentro dela:

Em seguida, realize o download e atualização dos arquivos com seguinte comando:

Adicionando suporte ao CAN

O kernel padrão do Linux e do Android não suporta o barramento CAN, sendo necessário adicionar esse suporte manualmente. Para isso, é necessário realizar uma pequena customização no processo de compilação do kernel, adicionando módulos específicos para o barramento CAN.

Customização do kernel Android

Para adicionar suporte do módulo MCP2515 se faz necessário customizar a compilação do kernel. Para isso, é necessário modificar o arquivo <kernel_dir>/common/build.config.arpi de acordo com o patch:

Foi adicionado modules e dtbs no alvo MAKE_GOALS do arquivo para compilar os módulos e os arquivos device tree. Já no alvo FILES foram adicionados o overlay do MCP2515, o módulo do kernel do MCP2515 e alguns módulos do CAN e SPI.

Para compilar o kernel com as modificações é necessário retornar para a pasta raiz do kernel e executar o seguinte comando:

Após a realização da compilação, sem erros, os arquivos resultantes estarão em: <kernel_dir>/out/arpi-5.10/dist/. Nesta pasta devem estar todos os arquivos definidos no target FILES do arquivo de configuração do kernel como mostrado pela Figura 1.

Figura 1: Arquivos gerados pela compilação do kernel Android

Customização do AAOS 13

Para realizar a integração do barramento CAN ao AAOS é realizada algumas customizações como, adicionar as ferramentas do can-utils e configurar a inicialização dos módulos do kernel referentes ao CAN e ao MCP2515 junto com a inicialização do sistema. O uso das ferramentas do can-utils é opcional, mas são importantes para o desenvolvimento e debug, pois com elas é possível enviar mensagens e monitorar a rede CAN.

Adicionando o conjunto de ferramentas can-utils ao AAOS

Primeiramente deve ser feito o download do repositório, e para isso o arquivo de manifest deve ser atualizado. Deve ser adicionado o seguinte conteúdo ao final do arquivo localizado em <android_dir>/.repo/manifests/default.xml:

O conteúdo adicionado se refere ao repositório do can-utils. A primeira linha indica a fonte remota que aponta para uma conta no GitHub e denomina o nome “github”. A segunda linha indica o repositório da conta que será baixado, no caso “can-utils”, define o local que será salvo, define a partir de qual fonte remota e revisão (branch) o repositório será baixado. Atente-se para escrever esse trecho antes do fechamento da tag . Após salvar a modificação, basta executar novamente o comando repo sync. Caso tenha sido executado o download com sucesso, o repositório estará salvo em: <android_dir>/external/can-utils/.

Adicionando os módulos do kernel ao AAOS

Nesta seção será realizada toda a integração da rede CAN no Android Automotivo. Para isso, é necessário adicionar os módulos e overlays do kernel gerados na compilação, de modo que a rede CAN e o módulo MCP2515 estejam operáveis após a inicialização do sistema.

Primeiro, serão concentrados todos os recursos necessários em uma pasta dentro do ambiente do AAOS, criada em <android_dir>/device/snappautomotive/rpi4_car/can/. Dentro da pasta can foi criada a pasta modules que irá armazenar os módulos gerados na compilação do kernel. Utilize o seguinte comando para copiar todos os módulos:

Em seguida, será criado um arquivo Makefile para “ensinar” o Android a compilar e copiar alguns arquivos. Na pasta <android_dir>/device/snappautomotive/rpi4_car/ crie o arquivo can.mk com o seguinte conteúdo:

O alvo PRODUCT_PACKAGES contém os programas da ferramenta can-utils para monitorar o tráfego da rede que serão compilados pelo sistema de compilação do Android. Já o alvo PRODUCT_COPY_FILES contém os arquivos de módulos que serão copiados para o sistema de arquivos, na pasta vendor, onde ficam os artefatos de software das fabricantes do AAOS no momento da compilação. Em seguida, na mesma pasta, crie um arquivo init.can.rc com o seguinte conteúdo:

Com esse conteúdo, o Android poderá inserir os módulos referente ao SPI, CAN e MCP2515 fazendo com que a rede CAN e o controlador MCP2515 sejam reconhecidos e se tornem operáveis. O arquivo init.can.rc será executado na inicialização do sistema. Após as modificações e os arquivos criados, a pasta can ficou organizada de acordo com a Figura 2.

Figura 2: Organização da pasta can/ com as modificações

Agora é necessário atualizar alguns arquivos para que as nossas customizações possam ser identificadas pelo Android no momento da compilação. No arquivo <android_dir>/device/snappautomotive/rpi4_car/rpi4_car.mk adicione no cabeçalho do arquivo, junto com os outros arquivos Makefile:

Ainda no mesmo arquivo, mas no final dele adicione:

Por último, na mesma pasta, mas no arquivo init.rpi4.rc adicione no cabeçalho a seguinte linha:

Configurando o arquivo de inicialização do sistema

Para tornar o módulo MCP2515 operável e reconhecido pelo kernel, é necessário atualizar o arquivo de configuração de inicialização do sistema, adicionando alguns parâmetros. Adicione as seguintes informações no arquivo:

<android_dir>/device/snappautomotive/rpi4_car/boot/config.txt:

A primeira linha é um parâmetro para habilitar o barramento SPI. A segunda linha adiciona a configuração de um overlay do módulo MCP2515 e seus parâmetros. O parâmetro oscillator corresponde a frequência do oscilador no qual o módulo controlador CAN opera, nesse caso eu escolhi 16MHz, mas 8MHz também seria uma opção válida [8]. O parâmetro interrupt indica o número do GPIO em que a interrupção vai ser configurada. Atente-se para conectar o pino INT do módulo MCP2515 no mesmo GPIO configurado pelo parâmetro. A escolha pelo GPIO25 foi baseada em outro tutorial, mas qualquer outro GPIO de entrada pode ser usado [9]. Com as modificações realizadas, agora podemos avançar para a compilação do AAOS.

Compilação do Android Automotivo

Antes de realizar a compilação, é necessário modificar o arquivo <android_dir>/device/snappautomotive/rpi4_car/BoardConfig.mk, adicionando o seguinte conteúdo na última linha:

Essa configuração permite que os módulos do kernel compilados anteriormente possam ser copiados para o sistema de arquivos do Android. Em seguida, a compilação é realizada com os seguintes comandos:

  1. Preparar o ambiente de compilação:
  1. Indicar o alvo para compilação
  1. Compilação efetiva

Os arquivos gerados pela compilação, sem erros, poderão ser encontrados na pasta <android_dir>/out/target/product/rpi4_car/.

Configuração do cartão micro SD

Estando com todas as imagens geradas, agora é necessário configurar as partições do cartão de memória para que as imagens sejam gravadas corretamente. Portanto, é necessário formatar o dispositivo com o seguinte comando:

O parâmetro <p> indica a partição do cartão micro SD. Caso você esteja utilizando um adaptador USB, essa partição será sda ou algo do tipo. Caso você utilize a entrada de cartão essa partição será mmcblk0 ou algo similar. Atente-se para formatar apenas a partição do seu cartão de memória e não a partição do seu sistema.

Após a formatação, o próximo passo é criar e configurar as partições do cartão. Para essa etapa foi utilizado o programa cfdisk.

Número da partiçãoTamanhoTipo
p1128MBW95 FAT32(LBA) & Boot (Flag)
p22,2GLinux (EXT4)
p31,2GLinux (EXT4)
p4O restante disponívelLinux (EXT4)
Tabela 1: Configuração das partições do cartão micro SD

Gravação das imagens

Após a configuração das partições você poderá gravar as imagens necessárias para o AAOS com os seguintes comandos a partir da pasta <android_dir>:

O arquivo system.img corresponde à imagem base do sistema operacional Android. O arquivo vendor.img corresponde à imagem dos artefatos de software do fabricante do SoC (Qualcomm, Mediatek, etc).

Em seguida, você também precisará criar sistemas de arquivos em p1 e p4 usando os seguintes comandos:

  1. Criar o sistema de arquivos de boot
  1. Criar o sistema de arquivos do usuário

O primeiro comando cria um sistema de arquivos FAT32 para a partição p1. Esse sistema de arquivo é utilizado para guardar os arquivos referentes ao boot do kernel e da placa. Já o segundo comando, é usado para criar um sistema de arquivos EXT4 com a label userdata. Esta partição contém aplicativos e dados instalados pelo usuário, incluindo dados de personalização.

Você precisará então montar a partição p1 para copiar os arquivos de inicialização para ela. Você pode utilizar os seguintes comandos a partir do diretório <android_dir>:

  1. Montar a partição p1
  1. Copiar arquivos de configuração do boot para a partição montada
  1. Copiar imagem relacionada ao kernel para a partição montada

A imagem ramdisk.img é uma pequena partição montada como somente leitura pelo kernel no momento da inicialização. Ela contém o init e alguns arquivos de configuração e é usada para iniciar o init, que montará o restante das imagens do sistema corretamente.

Por fim, as imagens, device trees e overlays gerados pela compilação do kernel serão copiadas para o cartão micro SD. Portanto, no diretório onde o kernel do Android está salvo execute os seguintes comandos:

  1. Copiar imagem do kernel para a partição
  1. Copiar os arquivos de device tree do SoC BCM2711 para a partição
  1. Copiar os overlays para configuração de hardware para a partição

Por padrão, os overlays sempre vão separados em uma pasta, portanto é necessário criar uma pasta dentro da partição.

Para a geração de imagem a partir do HDMI é necessário copiar o overlay responsável pela parte gráfica.

Por fim, é necessário copiar o overlay responsável pelo controle e configuração do MCP2515 e da rede CAN.

Após a realização desses passos, basta desmontar a partição e ejetar o dispositivo. Execute os comandos a seguir:

Acessando o Android Automotivo

Após toda a configuração realizada, é hora de conectar o cartão micro SD na placa, conectá-la a um display HDMI e a uma fonte DC 5V e 3A. Se tudo ocorrer bem, a logo da SnappAutomotive deve aparecer. A inicialização demora um pouco, portanto aguarde até que a interface do Android apareça. Nesta etapa será necessário o uso da ferramenta adb (vide Seção de Materiais e pré-requisitos)

Para configurar e usar o adb recomendo a leitura do artigo Compilando e Executando o Android Automotive OS para Raspberry Pi. Neste artigo, o autor traz mais detalhes sobre a comunicação adb e como se conectar remotamente a placa.

Experimento com a rede CAN

Após a realização da configuração do adb, será realizado um experimento com a rede CAN, com o objetivo de avaliar a integração do barramento CAN com o Android Automotivo 13.

Conexão entre o módulo MCP2515 e Raspberry Pi 4B

Para a realização do experimento é necessário conectar o módulo MCP2515 à placa. Seguindo o diagrama de circuito mostrado pela Figura 3, o módulo é conectado ao periférico SPI 0. Para evitar eventuais problemas, é recomendado que as conexões sejam realizadas com a placa desligada.

Figura 3: Circuito de conexão entre Raspberry Pi 4B e MCP2515

A Figura 3 ilustra como ficará o circuito utilizado nesse experimento com a rede CAN. A Tabela 2 contém maiores detalhes das conexões, informando em qual GPIO os pinos do módulo MCP2515 foram conectados.

MCP2515VCCGNDCSMISOMOSISCKINT
Raspberry Pi 4B5VGNDGPIO8GPIO9GPIO10GPIO11GPIO25
Tabela 2: Pinos de conexão entre Raspberry Pi 4B e MCP2515

Nesse caso foi utilizado os pinos do periférico SPI 0, mas nada impede que outras configurações sejam utilizadas, portanto, sinta-se livre para experimentar. Entretanto, é necessária uma atenção especial ao pino INT, pois ele deve ser o mesmo configurado no arquivo de inicialização do kernel. Caso queira alterar o número do GPIO, lembre-se de alterar o parâmetro no arquivo config.txt também.

Preparação para o experimento

Após a conexão dos dispositivos, vamos realizar o nosso experimento. Portanto, com a placa ligada e conectada ao Wi-Fi, realize os seguintes passos:

  1. Conecte-se a placa utilizando o adb

Para confirmar a conexão utilize:

  1. Entre como usuário root

Algumas operações para configuração da rede CAN e o Android não tem o “sudo”, portanto é necessário entrar como modo root. Execute o seguinte comando:

  1. Remonte a partição para habilitar o modo escrita

Por padrão, a partição /system é apenas para leitura, porém em alguns momentos é necessário escrever nessa partição. Portanto, para evitar problemas no experimento,remonte a partição com usuário root da seguinte forma:

  1. Entre no sistema de arquivos da placa

O experimento será feito dentro do sistema Android, portanto precisamos entrar no sistema de arquivos da placa. Após os passos anteriores, execute:

Após as seguintes configurações e ações, você deve estar dentro do sistema. Uma indicação para isso é o prompt “rpi4_car:/ #”. Dentro do sistema, vamos analisar as mensagens e verificar se o kernel reconheceu o dispositivo MCP2515 e os módulos relacionados ao barramento CAN. Para isso, execute:

O comando acima irá filtrar as mensagens do kernel baseado na expressão regular “(mcp|can)”, que procurará as palavras “can” ou “mcp” sem distinção entre maiúsculas e minúsculas, retornando assim, apenas as mensagens que têm o nosso interesse.

Figura 4: Mensagens do kernel filtradas

A Figura 4 é um recorte do resultado do comando anterior, com foco nas mensagens do barramento CAN e do dispositivo MCP2515. As três primeiras linhas indicam o sucesso na inserção e no reconhecimento dos módulos “can.ko”, “can-raw.ko” e “can-dev.ko”. A última linha mostra o sucesso na inserção e no reconhecimento do módulo “mcp251x.ko” e do overlay “mcp2515-can0.dtbo”. Além disso, no reconhecimento do periférico spi0.0 e interface de rede can0. Qualquer mensagem diferente dessas mostradas pela Figura 4 indica que o processo de inserção falhou, portanto revise seus passos anteriores.

Realização do experimento

Após a configuração realizada anteriormente, o CAN é reconhecido como uma interface de rede (e.g. lo, wlan0, eth0), portanto é possível gerenciá-lo como uma dessas interfaces. Após o reconhecimento dos drivers, a interface can0 fica disponível para ser utilizada, verifique com o comando:

Figura 5: Interface de rede can0

A Figura 5 é um recorte do comando executado, ela mostra a interface can0, porém a rede CAN ainda precisa ser levantada e configurada. Para isso, execute o seguinte comando (ainda com usuário root):

O comando acima levanta a interface de rede can0, configura o seu tipo e sua taxa de transmissão. Para esse experimento foi utilizada a taxa de 500kbps, mas de acordo com a ISO- 11898-1:2015 a taxa de comunicação varia de 125kbps a 1Mbps, sendo a fabricante de veículos responsável pela escolha. Portanto, sinta-se livre para escolher a velocidade. Além disso, o modo loopback também foi ativado. Para desabilitar esse modo, executar os comandos:

Uma rede CAN é formada por no mínimo dois nós (ou dois controladores). Neste artigo apenas um será utilizado, sendo necessária a configuração em loopback, de modo que as mensagens CAN sejam enviadas e lidas de forma interna pelo próprio controlador.

Para a realização do experimento são necessários dois terminais com o adb conectado à placa. Com a interface de rede levantada, execute em um dos terminais o programa:

No outro terminal, execute o programa:

O programa “candump” é usado para ler as mensagens que chegam na interface can0. Já o programa “cangen” é usado para enviar um tráfego de mensagens randômicas para a interface can0. Algumas opções são passadas para o programa “cangen”. A opção “-vv” serve para determinar o nível de detalhes na impressão das mensagens enviadas, permitindo a visualização de cada mensagem enviada. Por último, a opção “-n 10” informa a quantidade de mensagens a serem enviadas, neste caso foram dez. Você pode checar mais opções passando a opção “–help”. Essas ferramentas são do pacote can-utils instalado no começo dessa jornada.

Figura 6: Geração de mensagens pelo cangen

A Figura 6 ilustra a geração de pacotes randômicos realizados pelo programa cangen. As mensagens geradas possuem um padrão definido pela ISO-11898. Observando a primeira mensagem, o campo “can0” corresponde ao nome da interface que está enviando a mensagem, o campo “63C” corresponde ao ID dessa mensagem (em hexadecimal), o campo “[8]” corresponde ao DLC (Data Length Code) da mensagem, que indica o tamanho da mensagem em bytes, que no caso são oito. Por fim, o último campo corresponde ao dado que será enviado, podendo ser a leitura de um sensor ou uma mensagem de erro, depende da aplicação. Esses valores podem variar bastante, mas em qualquer comunicação CAN esses campos estarão presentes, com exceção do nome da interface.

A Figura 7 mostra a leitura das mensagens CAN realizadas pelo programa candump. É possível notar o mesmo padrão no formato das mensagens, explicado no parágrafo anterior, além do mesmo conteúdo, provando que a comunicação foi realizada corretamente. Entretanto, existe uma pequena diferença. Há uma duplicação no recebimento de cada mensagem gerado pela configuração do modo loopback. Não haveria duplicação de pacotes em comunicações entre nós distintos.

A rede aqui desenvolvida foi formada por apenas um nó, mas ela é totalmente escalável, pois o CAN tem a característica de ser multi-mestre. Portanto, não se limite apenas ao exemplo mostrado, você pode conectar outros vários controladores e formar uma rede com vários dispositivos. Atente-se às conexões, lembre-se de conectar todos os dispositivos ao mesmo par de fios (CAN High e CAN Low) e escolher a mesa taxa de transmissão para os nós. O artigo Barramento CAN entre Arduinos UNO mostra uma comunicação CAN entre dois nós e pode servir de base para integrar a Raspberry nessa rede.

Figura 7: Leituras das mensagens geradas pelo cangen utilizando o candump

Considerações Finais

Diante dos diversos avanços tecnológicos presentes na área automotiva, a presença de um sistema operacional específico para veículos é bastante interessante, pois dá liberdade para realizar diversas customizações e integrações com outros sistemas para monitoramento do veículo e apoio ao motorista, por exemplo [11].

Esse artigo abordou a integração e o uso do barramento CAN e do módulo MCP2515 no Android Automotivo 13, em uma Raspberry Pi 4B; mostrou como baixar e compilar o Android e o seu kernel, além de realizar configurações e compilação de módulos específicos para essa integração. Além disso, introduziu o conjunto de ferramentas can-utils, que permitiu uma fácil interação com a rede CAN.

Espero que esse artigo tenha despertado a curiosidade sobre sistemas embarcados na área automotiva e que também sirva de ponto de partida para replicar ou até expandir o que foi mostrado aqui, bem como estudar sobre CAN e o AAOS.

Esse texto contou com a coautoria de Álison Venâncio, Levy Gabriel e Robert Cabral.

Referências

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Home » Raspberry Pi » Integrando o barramento CAN ao Android Automotivo 13

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Comentários:
Notificações
Notificar
3 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Thales Silva
Thales Silva
01/01/2024 09:44

Muito bom!

Carlos Henrique
Carlos Henrique
18/12/2023 17:29

Exelente artigo.

José Batista
José Batista
18/12/2023 12:33

Certamente um trabalho de grande relevância. Fico imensamente agradecido por repassar seus conhecimentos Samuel Henrique. E esse trabalho ganha ainda mais importância no contexto tecnológico do Brasil atual.

Talvez você goste: