GT-511C3 Fingerprint Scanner with STM32F407G Microcontroller - c

I am working on a project that requires using the GT-511C3 fingerprint scanner with a STM32F407G microcontroller board. I am using Keil uvision 5 and can't figure out how to initialize and turn on the scanner. I've written this code and it seems correct, based off the datasheet, for starting up the scanner and sending the start commands. I've used an oscilloscope to verify that the values are being sent correctly and it seems they are but the scanner is not lighting up. I'm completely lost on what I could be doing wrong or what I could be missing. I've verified the scanner is wired correctly and connected to the board accordingly. Any help would be gr8 :)
Scanner: https://www.digikey.com/catalog/en/partgroup/fingerprint-scanner-ttl-gt-511c3/56722
Current Code:
#include "stm32f4xx.h" // Device header
int i=0;
int z=0;
int main(){
// ENABLE CLocks for PORT C and UART4
RCC -> AHB1ENR = 0x00000004; //Enable the clock to GPIO port GPIOCEN
RCC -> APB1ENR = 0x00080000; //Enable the clock to UART 4 UART4EN
// Set Mode Pins on Port C pins 10 and 11 to Alternate Function
GPIOC->MODER|=0x00A00000;
// Set Alternate Function Register for Port C 10 and 11
GPIOC->AFR[1]|= 0x00008800; //AFR High = enabled
// UART setup:
// 8 data bits (default), no parity (default), one stop bit (default) & no flow control (default)
// UART Baud Rate
UART4->BRR = 0x683;
// Enable TRANSMITTER (TE bit)
UART4->CR1 |= (1<<3);
UART4->CR1 |= (1<<2);
// WE WANT TO TRANSMIT SO ENABLE TRANSMIT INTERRUPT
UART4->CR1 |=(1<<7);
// Enable UART (UE bit in CR1 register)
UART4->CR1 |=(1<<13);
// NVIC to handle interrupts
__enable_irq();
NVIC_ClearPendingIRQ(UART4_IRQn);
NVIC_SetPriority(UART4_IRQn,0);
NVIC_EnableIRQ(UART4_IRQn);
while(1){};
}
// Interrupt reoutine for UART1
void UART4_IRQHandler(void){
// TX IRQ
if(((UART4->SR)&(1<<7))>0){ //if txe flag in sr is on then
if(z==0){
int command[]={0x55,0xAA, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x01};
UART4->DR=command[i]; // command start code
i=i+1;
if(i==12){
z=1;
i=0;
}
}
if(z==1){
int command1[]={0x55,0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x13, 0x01};
UART4->DR=command1[i]; // command start code
i=i+1;
if(i==12){
z=0;
i=0;
}
}
}
}

Related

unsigned char array breaks at zero bytes in Azure Sphere SDK when passing to a function

I am using (1)Azure Sphere MT3620 Starter Kit and (2)RS485 CLICK 5V and (3)Geovan Board
Here is the setup (I don't have latest picture, so #2 is swapped to first slot in the MT3620)
My MT3620 is registered all good with Azure IoTHub and pushing all telemetry data to cloud. Now I am trying to sent some HEX commands from MT3620 to Geovan Board via RS485 CLICK 5V
Here is my Calling code
//RS485 to Geovan to Update Registry values
unsigned char updateAllChannelData[] = { 0x01, 0x06, 0x00, 0x19, 0x00, 0x01, 0x99, 0xCD };
SendUartMessage(uartFd, updateAllChannelData, sizeof(updateAllChannelData));
delay(10);
//RS485 to Geovan to Read all channels
unsigned char readAllChannel[] = { 0x01, 0x03, 0x00, 0x01, 0x00, 0x10, 0x15, 0xC6 };
SendUartMessage(uartFd, readAllChannel, sizeof(readAllChannel));
delay(1.5); //20
when data is passed to SendUartMessage both arrays (updateAllChannelData and readAllChannel) breaks at 0x00 so final command being passed to Geovan Board is incomplete and no response is received.
Here is SendUartMessage method
static void SendUartMessage(int uartFd, const char* dataToSend, size_t totalBytesToSend)
{
// dataToSend breaks at 0x00 right here not after executing any lines below
// First command array becomes {0x01, 0x06}
// Second command array becomes {0x01, 0x03}
size_t totalBytesSent = 0;
int sendIterations = 0;
close(r1PinFd);
r1PinFd = GPIO_OpenAsOutput(MIKROE_PWM, GPIO_OutputMode_PushPull, GPIO_Value_High);
while (totalBytesSent < totalBytesToSend) {
sendIterations++;
// Send as much of the remaining data as possible
size_t bytesLeftToSend = totalBytesToSend - totalBytesSent;
const char* remainingMessageToSend = dataToSend + totalBytesSent;
ssize_t bytesSent = write(uartFd, remainingMessageToSend, bytesLeftToSend);
if (bytesSent == -1) {
Log_Debug("ERROR: Could not write to UART: %s (%d).\n", strerror(errno), errno);
exitCode = ExitCode_SendMessage_Write;
return;
}
totalBytesSent += (size_t)bytesSent;
}
int c, d;
sleep(5);
close(r1PinFd);
r1PinFd = GPIO_OpenAsOutput(MIKROE_PWM, GPIO_OutputMode_PushPull, GPIO_Value_Low);
Log_Debug("Sent %zu bytes over UART in %d calls.\n", totalBytesSent, sendIterations);
}
FYI: I have tested these commands as below
Connect Geovan directly to PC
using Hercules SETUP utility open com port on which Geovan is connected
send HEX command "0x01, 0x06, 0x00, 0x19, 0x00, 0x01, 0x99, 0xCD" wait 10 seconds
send HEX command "0x01, 0x03, 0x00, 0x01, 0x00, 0x10, 0x15, 0xC6" wait 10 seconds
received expected response
This confirms from Geovan these commands as sent and responded correctly. So the challenge is sending same commands from MT3620 through RS485 CLICK 5V to Geovan Board.
Can someone point out the what am I missing over here?
Update:
Before stepping in to function, this is how my array looks
After stepping in to the function, this is what it looks like

Significance of 0xff

I was wondering was 0xff, 0x00, and 0x0f represent. TRISA, TRISB, and TRISC are the ports being used on my board.
void main()
{
TRISA = 0xff;
TRISB = 0x00;
TRISC = 0x00;
ADCON1 = 0x0f;
}
TRISA is the tristate controller bits for I/O line A. This turns on or off the tristate gates that select whether the output register powers the pins or not. With the tristates off, the pins are input pins.
I'm not absolutely sure since I haven't checked the manual in over 10 years but I think 0xFF turns on all the tristates, so all the pins are input pins. I could have it backwards though.

How to use Modbus with Microchip PIC24

First time using Modbus. I'm trying to send a request to read a temperature value from my slave device (ID is 0x01). I'm sending the command through UART and viewing command on my logic analyser.
Here is my code:
void temp_sensor()
{
//Transmit RTU to Inisitu probe to fetch Temperature and units
Flow_Control_SetHigh();
unsigned char TempRTU[]= {0x01, 0x03, 0x00, 0x2D, 0x00, 0x02, 0x54, 0x02};
int i;
int data_len = 8;
for (i = 0; i < data_len; i++) {
UART1_Write(TempRTU[i]);
}
}
0x01: Slave ID:
0x03: function code:
0x002D: Read temperature register:
0x0002: Read 2 registers:
0x5402: CRC Checksum:
The hex string is correct when viewing through UART on my analyser, however when setting the analyser to view Modbus, the string is not even close to being correct. I've attached a screenshot of my analyser while viewing the Modbus signal.
Has anyone got experience with Modbus and PIC microcontrollers?

Having timer collision issue with using Servo and SoftwareSerial

I'm having timer collision problems with using Servo.h and SoftwareSerial.h on Arduino Nano board. And now I need 2 pairs of Serial pins by using NFC Module and Arduino's Serial Monitor on my laptop.
If the information I got is not wrong, there are three timers (timer0, timer1, timer2) available in Nano board. As I heard timer1 is 16bit timer, and both Servo.h and SoftwareSerial.h use that timer1 at the same time on Nano board that's why they can't avoid timer collision issue.
Yet I need to use both header files without timer collision. In this case, what should I do? Do I have to modify Servo.h file for not using timer1?
Because all I do with my Servo Motor is controlling angular position.
Therefore, using 16bit-timer is of no use in this project I'm proceeding unless I use PWM control.
So, at this point, I want to use timer0 or timer2 (both are 8 bit-timer) instead of using timer1. If not, the timer1 from both header files of Servo and Software will be collide.
Following is the source code I use.
const unsigned char wake[24]={
0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module
const unsigned char firmware[9]={
0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD4, 0x02, 0x2A, 0x00};//
const unsigned char tag[11]={
0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command
const unsigned char std_ACK[25] = {
0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0C,
0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00};
unsigned char old_id[5];
unsigned char receive_ACK[25];//Command receiving buffer
//int inByte = 0; //incoming serial byte buffer
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#define print1Byte(args) mySerial.write(args)
#define print1lnByte(args) mySerial.write(args),mySerial.println()
#else
#include "WProgram.h"
#define print1Byte(args) mySerial.print(args,BYTE)
#define print1lnByte(args) mySerial.println(args,BYTE)
#endif
#include <Servo.h>
#include <NeoSWSerial.h>
NeoSWSerial mySerial(5,6);
volatile uint32_t newlines = 0UL;
Servo sv;
int pos1=0; //initial value = 93 degree
int pos2=180;
int sw1 = 4;
static void handleRxChar( uint8_t c )
{
if (c == '\n')
newlines++;
}
void setup(){
mySerial.attachInterrupt( handleRxChar );
pinMode(sw1, INPUT_PULLUP);
sv.attach(9);
Serial.begin(9600); // open serial with PC
mySerial.begin(9600); //open serial1 with device
//Serial2.begin(115200);
wake_card();
delay(100);
read_ACK(15);
delay(100);
display(15);
}
void loop(){
send_tag();
read_ACK(25);
delay(100);
if (!cmp_id ()) { //nfc tag
if (test_ACK ()) {
display (25);
sv.write(pos1);
delay(2500);
sv.write(pos2);
}
}
else if (cmp_id()){ // switch
if(digitalRead(sw1) == LOW){
sv.write(pos1); // waits 15ms for the servo to reach the position
}
else if(digitalRead(sw1) == HIGH){
sv.write(pos2);
}
}
copy_id ();
}
void copy_id (void) {//save old id
int ai, oi;
for (oi=0, ai=19; oi<5; oi++,ai++) {
old_id[oi] = receive_ACK[ai];
}
}
char cmp_id (void){//return true if find id is old
int ai, oi;
for (oi=0,ai=19; oi<5; oi++,ai++) {
if (old_id[oi] != receive_ACK[ai])
return 0;
}
return 1;
}
int test_ACK (void) {// return true if receive_ACK accord with std_ACK
int i;
for (i=0; i<19; i++) {
if (receive_ACK[i] != std_ACK[i])
return 0;
}
return 1;
}
void send_id (void) {//send id to PC
int i;
Serial.print ("ID: ");
for (i=19; i<= 23; i++) {
Serial.print (receive_ACK[i], HEX);
Serial.print (" ");
}
Serial.println ();
}
void UART1_Send_Byte(unsigned char command_data){//send byte to device
print1Byte(command_data);
#if defined(ARDUINO) && ARDUINO >= 100
mySerial.flush();// complete the transmission of outgoing serial data
#endif
}
void UART_Send_Byte(unsigned char command_data){//send byte to PC
Serial.print(command_data,HEX);
Serial.print(" ");
}
void read_ACK(unsigned char temp){//read ACK into reveive_ACK[]
unsigned char i;
for(i=0;i<temp;i++) {
receive_ACK[i]= mySerial.read();
}
}
void wake_card(void){//send wake[] to device
unsigned char i;
for(i=0;i<24;i++) //send command
UART1_Send_Byte(wake[i]);
}
void firmware_version(void){//send fireware[] to device
unsigned char i;
for(i=0;i<9;i++) //send command
UART1_Send_Byte(firmware[i]);
}
void send_tag(void){//send tag[] to device
unsigned char i;
for(i=0;i<11;i++) //send command
UART1_Send_Byte(tag[i]);
}
void display(unsigned char tem){//send receive_ACK[] to PC
unsigned char i;
for(i=0;i<tem;i++) //send command
UART_Send_Byte(receive_ACK[i]);
Serial.println();
}
Summary
I am having timer collision issue with using Servo.h and SoftwareSerial.h.
they both share timer1 at the same time. To avoid this collision issue and make these two work fine, what should I do? Should I do something with the source code like by adding up few lines of code or modify those header files?
Normally, I would have suggested AltSoftSerial as the alternative to SoftwareSerial (read more here), but it also conflicts with the Servo library's TIMER1 use. It can only be used on two specific pins.
I think my NeoSWSerial would do the trick. It re-uses the micros() clock (TIMER0) and Pin Change interrupts to implement a software serial port. This limits it to bauds rates 9600, 19200 and 38400, but it is much more efficient than SoftwareSerial. It can be used on any two pins.
Update
I would not suggest using a software serial port at 115200, as it can be unreliable above 38400. You might be able to send a baud rate configuration command to the NFC module to set it to a lower rate.
BTW, if you are sending information (not just receiving), all software serial port libraries disable interrupts during transmission, except AltSoftSerial... which you can't use. Just be aware of that, because it may affect your Servo when you transmit on NeoSWSerial.
Also, be sure you are using one of the PWM pins for the servo. If the Servo library is creating the PWM signal with software (just like a software serial port), the CPU won't have time for much else.
It might be better to put the NFC module on the hardware serial port, Serial. For debug prints, use NeoSWSerial connected to a TTL Serial-to-USB converter. Then open the Serial Monitor on that converter's COM port. Remove the debug later, because transmitting disables interrupts.
There are other boards that have additional UARTS. For example, an Arduino Leo (ATMega32U4 MCU) has an extra serial port, Serial1, that you could use for the NFC. Serial would still be available for debug prints.

Polling uBlox MAX-6Q

I'm currently working on a HAB (High Altitude Balloon) project, and so far, all has gone swimmingly.
I'm using an Arduino uno R3 as my main controller for this project, however, I'm struggling with the GPS side of things here.
Follwing the fantastic tutorial at UK-HAS (http://ukhas.org.uk/guides:ublox6) I'm currently working with the uBlox MAX-6Q GPS module.
I've played around with the code supplied on the tutorial, and am in the process of testing with the following sketch:
#include <SoftwareSerial.h>
SoftwareSerial GPS(3,2);
byte gps_set_success = 0;
void setup()
{
Serial.begin(9600);
GPS.begin(9600);
GPS.print("$PUBX,41,1,0007,0003,4800,0*13\r\n");
GPS.begin(4800);
GPS.flush();
uint8_t setNav[] = {
0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00,
0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC };
/*while(!gps_set_success)
{
sendUBX(setNav, sizeof(setNav)/sizeof(uint8_t));
gps_set_success = getUBX_ACK(setNav);
}*/
gps_set_success = 0;
GPS.println("$PUBX,40,GGA,0,0,0,0*5A");
GPS.println("$PUBX,40,GSA,0,0,0,0*4E");
GPS.println("$PUBX,40,RMC,0,0,0,0*47");
GPS.println("$PUBX,40,GSV,0,0,0,0*59");
GPS.println("$PUBX,40,VTG,0,0,0,0*5E");
GPS.println("$PUBX,40,GLL,0,0,0,0*5C");
}
void loop()
{
printGPSData();
delay(3000);
}
void printGPSData()
{
Serial.println("Polling: $PUBX,00*33");
GPS.println("$PUBX,00*33");
while (GPS.available())
{
if (GPS.available() > 0)
{
char c = GPS.read();
Serial.write(c);
}
}
Serial.println();
}
void sendUBX(uint8_t *MSG, uint8_t len)
{
for (int i = 0; i<len; i++)
{
GPS.write(MSG[i]);
Serial.print(MSG[i], HEX);
}
GPS.println();
}
boolean getUBX_ACK(uint8_t *MSG)
{
uint8_t b;
uint8_t ackByteID = 0;
uint8_t ackPacket[10];
unsigned long startTime = millis();
Serial.print(" * Reading ACK response: ");
ackPacket[0] = 0xB5;
ackPacket[1] = 0x62;
ackPacket[2] = 0x05;
ackPacket[3] = 0x01;
ackPacket[4] = 0x02;
ackPacket[5] = 0x00;
ackPacket[6] = MSG[2];
ackPacket[7] = MSG[3];
ackPacket[8] = 0;
ackPacket[9] = 0;
for (uint8_t i=2; i<8; i++)
{
ackPacket[8] = ackPacket[8] + ackPacket[i];
ackPacket[9] = ackPacket[9] + ackPacket[8];
}
while(1)
{
if (ackByteID > 9)
{
Serial.println("(SUCCESS!)");
return true;
}
if (millis() - startTime > 3000)
{
Serial.println("(FAILED!)");
return false;
}
if (GPS.available())
{
b = GPS.read();
if (b == ackPacket[ackByteID])
{
ackByteID++;
Serial.print(b,HEX);
}
else
{
ackByteID = 0;
}
}
}
}
I've been struggling with 2 issues here. I'm hitting the timeout in the getUBX_ACK method, thus meaning, no response from the GPS module to confirm the setting change. This isn't currently crucial as if need be, I can configure this through uCenter, and add a battery to preserve the settings.
However, the main issue I am facing is when I run this sketch with the setNav block in the setup commented out, I am able to turn off all the automatic NMEA sentences, and poll the module, but upon polling, I am greeted with the following:
Polling: $PUBX,00*33
followed by a number of invalid characters. (Rectangles)
I've checked baud rates stop bits, parity etc. along with the actual data line connections, but cannot seem to find the source of this. It suggests bad data lines/encoding/ to me, but I was wondering if this was something anybody else had ever experienced?
EDIT:
So, after more testing, it would appear that the SoftwareSerial library is NOT at fault here. I tried first, writing to an OpenLog using the SoftwareSerial GPS ipput, and then by hooking the GPS Tx directly into the OpenLog Rx. Same story. Opening the resulting file in Notepad++ yeilds a lovely bunch of 'NULL' characters. I can only presume something in the way the GPS is configured at runtime is causing a problem.
Bypassing the Arduino, and turning off the sentences and polling the GPS directly through serial works with no problems, the data is returned perfectly.
So, I'm feeling a bit daft here, there is an issue, but not with the GPS, I'll ask as a seperate question. It would appear I'm having problems with the SoftwareSerial library.
The SoftwareSerial library cannot use multiple soft serial ports at the same time, it would appear that despite many suggestions otherwise, I cannot switch between sof serial ports, as I am unable to begin() the second port, it would appear that the port first declared is to be unusable.

Resources