Manual
do
Maker
.
com
Garimpando pela Internet, acabei me deparando com uma ferramenta espetacular, que faz uso de diversos recursos do Qt. O Serial Studio é uma ferramenta que serve para diversos tipos de diagnósticos. Pois é, um laboratório não é feito só de hardware. Mas de que modo ele pode ser usado como uma ferramenta? - Vamos conhecê-lo primeiro.
A primeira coisa que dá vontade de fazer é utilizá-lo como dashboard permanente. Não que a ideia seja ruim, mas na verdade ele é uma ferramenta para aferir o funcionamento de seus periféricos conectados a uma MCU. E como a comunicação é serial, serve para qualquer MCU: Raspberry, Banana Pi, Orange Pi ou qualquer outro hardware que ofereça uma interface UART.
Ele possui uma série de widgets para visualização, que são adaptáveis a diversas saídas, como dados únicos ou arrays. Descrevo-os adiante.
O widget acelerômetro do Serial Studio mede a força G em cada axis e mostra em um gauge similar aos encontrados em aeronaves.
Esse widget é usado para indicar o valor de medições em relação a carga mínima e máxima. Serve para medição de baterias, nível d'água, medição de recursos de software etc.
Esse é apaixonante. Esse widget é utilizado para aferição de giroscópio.
E a última imagem de Ctrl+Chups do projeto: o mapa, para utilizar com GPS. Daqui em diante as imagens são geradas aqui mesmo, com os testes que fiz para comprovar a usabilidade.
O protocolo é baseado em json, que pode ser implementado de duas maneiras: ou na MCU, ou no computador. Fui direto para o computador, pois assim simplifica a implementação do recurso em qualquer projeto pronto, sem precisar mais desenvolvimento. Mas temos que conhecer a estrutura para montar nosso json localmente. É fácil, confira.
Para motivá-lo, fiz uma leitura analógica em um ESP32 para mostrar a simplicidade. No ESP32 fiz apenas isso:
void loop() {
String msg = "/*Analog 4,"+String(analogRead(4)) +"*/";
Serial.println(msg);
delay(100);
}
O formato é composto por:
Início de mensagem: /*
Título do projeto: Usei "Analog 4", mas pode ser qualquer coisa, com ou sem espaço.
Mensagem: No caso, fiz uma leitura analógica.
Fim de mensagem:*/
Esse é o formato mínimo, dispensando o uso de json na MCU. Do lado do Serial Studio, criamos o arquivo json a importar:
{
"t":"%1",
"g":[
{
"t":"Sensor Readings",
"d":[
{
"t":"Analog test",
"v":"%2",
"g":true,
"u":"A4"
}
]
}
]
}
Vamos aos detalhes.
Criamos a estrutura dentro de chaves, definimos o título (t) e então criamos um grupo (g). Dentro do grupo temos título, widget e dataset.
O título é obrigatório e pode ser qualquer coisa que desejar.
É opcional esse parâmetro. Temos 4 possíveis escolhas:
O dataset é um array, contendo 1 item obrigatório e 3 opcionais:
O w do dataset depende do tipo de widget do grupo. Para giroscópio e acelerômetro temos:
Para map temos:
Para tanque temos:
O Serial Studio também pode criar um arquivo CSV com todas as leituras recebidas através do dispositivo pela serial, e o arquivo pode ser usado para análise e processamento de dados com MATLAB.
Os widgets podem ser repetidos através de diferentes grupos.
Como citei lá no começo, tem duas maneiras de fazer essa comunicação. Uma delas, formatando o json na MCU; a outra, formatando uma string a enviar pela serial.
Por que eu prefiro fortemente formatar uma string e enviar pela serial? - Simples: pego qualquer projeto pronto que precise ser depurado e só incluo uma string formatando os dados ao final do processamento. Não preciso mexer no código e depois de concluído o debug, removo a string! Magnífico!
Não é por utilizar o formato string que não seja necessário conhecer a estrutura, já que para gerar os gráficos será necessário compor os widgets localmente. O que fiz para criar o arquivo localmente foi utilizar um trecho do formato que seria composto na MCU. O exemplo do projeto dispõe essa referência, da qual podemos extrair as partes desejadas:
{
"t":"%1",
"g":[
{
"t":"Mission Status",
"d":[
{
"t":"Runtime",
"v":"%2",
"u":"ms"
},
{
"t":"Packet count",
"v":"%3"
},
{
"t":"Battery voltage",
"v":"%4",
"g":true,
"u":"V"
}
]
},
{
"t":"Sensor Readings",
"d":[
{
"t":"Temperature",
"v":"%5",
"g":true,
"u":"°C"
},
{
"t":"Altitude",
"v":"%6",
"u":"m"
},
{
"t":"Pressure",
"v":"%7",
"u":"KPa",
"g":true
},
{
"t":"External Temperature",
"v":"%8",
"g":true,
"u":"°C"
},
{
"t":"Humidity",
"v":"%9",
"g":true,
"u":"°C"
}
]
},
{
"t":"GPS",
"w":"map",
"d":[
{
"t":"GPS Time",
"v":"%10"
},
{
"t":"Longitude",
"v":"%11",
"u":"°N",
"w":"lon"
},
{
"t":"Latitude",
"v":"%12",
"u":"°E",
"w":"lat"
},
{
"t":"Altitude",
"v":"%13",
"u":"m"
},
{
"t":"No. Sats",
"v":"%14"
}
]
},
{
"t":"Accelerometer",
"w":"accelerometer",
"d":[
{
"t":"X",
"v":"%15",
"u":"m/s^2",
"g":true,
"w":"x"
},
{
"t":"Y",
"v":"%16",
"u":"m/s^2",
"g":true,
"w":"y"
},
{
"t":"Z",
"v":"%17",
"u":"m/s^2",
"g":true,
"w":"z"
}
]
},
{
"t":"Gyroscope",
"w":"gyro",
"d":[
{
"t":"X",
"v":"%18",
"u":"rad/s",
"g":true,
"w":"x"
},
{
"t":"Y",
"v":"%19",
"u":"rad/s",
"g":true,
"w":"y"
},
{
"t":"Z",
"v":"%20",
"u":"rad/s",
"g":true,
"w":"z"
}
]
}
]
}
O Serial Studio substitui os parâmetros %n com os valores correspondentes separados por vírgula, como na mensagem que compus no ESP32. Para essa "linguiça" do exemplo, ficaria desse jeito:
/*KAANSATQRO,%s,%s,%s,%s,%s,%s,%,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s*/
Fácil ou não? Agora veja a sintaxe para cada um dos widgets das imagens mais acima:
{
"t":"Accelerometer", # Group title
"w":"accelerometer", # Widget type for this group
"d":[ # Dataset array
{
"t":"X-Acceleration", # Dataset title
"v":"%current_x_value%", # Current value of dataset
"w":"x" # Corresponding widget option for this dataset
},
{
"t":"Y-Acceleration", # Dataset title
"v":"%current_y_value%", # Current value of dataset
"w":"y" # Corresponding widget option for this dataset
},
{
"t":"Z-Acceleration" # Dataset title
"v":"%current_z_value%", # Current value of dataset
"w":"z" # Corresponding widget option for this dataset
}
]
}
{
"t":"Battery voltage", # Dataset title
"v":"%current_value%", # Dataset value
"w":"bar", # Widget type
"min":0, # Minimum value in range
"max":5 # Maximum value in range
}
{
"t":"Gyroscope", # Group title
"w":"gyro", # Widget type
"d":[
{
"t":"X", # Dataset title
"v":"%current_value%, # Dataset value
"w":"yaw" # Corresponding widget option (yaw)
},
{
"t":"Y", # Dataset title
"v":"%current_value%", # Dataset value
"w":"roll" # Corresponding widget option (roll)
},
{
"t":"Z", # Dataset title
"v":"%current_value%", # Dataset value
"w":"pitch" # Corresponding widget option (pitch)
}
]
}
{
"t":"GPS", # Group title
"w":"map", # Widget type
"d":[
{
"t":"Longitude", # Dataset title
"v":"%longitude%", # Dataset value
"w":"lon" # Corresponding widget option (longitude)
},
{
"t":"Latitude", # Dataset title
"v":"%latitude%", # Dataset value
"w":"lat" # Corresponding widget option (latitude)
}
]
}
Eu fiz a compilação, já que o programa é feito em Qt e eu tenho o ambiente pronto para execução do setup, mas em Releases você encontra binários prontos para Windows, Mac e Linux.
Claro, não dá pra passar sem vídeo. Fiz uma apresentação de uma leitura do gerador de sinal PWM e uma leitura de um microfone (que utilizei em outro artigo para mostrar como fazer streaming de áudio do ESP32 para o Raspberry por WiFi) aqui nesse vídeo, em nosso canal Dobitaobytebrasil no Youtube.
O arquivo json utilizado para o vídeo é esse a seguir, caso deseje reproduzir ou ter um ponto de partida:
{
"t":"%1",
"g":[
{
"t":"Sound test",
"d":[
{
"t":"Microphone",
"v":"%2",
"g":true,
"u":"signal"
}
]
},
{
"t":"%3",
"d":[
{
"t":"Readings",
"v":"%4",
"g":true,
"u":"PWM"
}
]
}
]
}
Até a próxima!
Revisão: Ricardo Amaral de Andrade
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.