Hi everybody, I`m doing a project in which a microcontroller realises an A/D conversion of 8 channels and send then to the computer using the USB, over one serialport interface.
On the PC, I`m using a VB software that receives and store the data from the microcontroller. On this program, the user
enters with the sampling time and the name of the storage file. So, to start the pickup, the user must click on the "Coletar"
button. Then the program will start a thread that does the pickup.
I`m using the following convention for the data of each channel
byte 1 : A0000XXX, where X represents the value and
A equals 1 if the current channel is the channel 0 or equals 0 case else
byte 2 : 0XXXXXXX
So, the thread receives the data and discard it until it finds the byte 1 of the channel 0. After the thread keeps continuously receiving the data, converting it to a number on the range 0-1023 and storing it on a file.
The problem is that, when I open the resultant file, i see that the program looses some data at some points. I`ve made
tests with a 2s sampling, and it always loose exactly 34 frames (one sampling of all the 8 channels) per file. I`ve looked on the code and I couldn`t find the reason for this.
I`ve already tested the hardware with a terminal program, and there is no problem on the transmition in this case. The
baudrate of the serialport is 500000bps. I`m putting the source-code of the thread below.
Thanks for the attention
Private Sub ThreaColeta_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles ThreadColeta.DoWork
Dim sync As Byte = 0 ' byte para busca de sincronismo
Dim frame As Byte() ' frame de dados
Dim len As Integer ' Tamanho do conjunto de dados lido em bytes
Dim ch As Short = 0 ' Nmero do canal sendo lido (0-7)
Dim i As Short = 0
Dim temp As Short() ' Variável temporária de conversão do valor de 16 bits de cada canal
Dim sincro As Short = 0 'Variável que indica se a transmissão saiu do sincronismo
Dim nframe As Integer ' Nmero da frame atual
Dim tnstring As String ' Conversão da trial number para string com 3 dígitos
Control.CheckForIllegalCrossThreadCalls = False 'Desabilita verificacao de acesso
'de propriedades externas pelo Thread
frame = New Byte() {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
temp = New Short() {0, 0, 0, 0, 0, 0, 0, 0}
btnRefazer.Enabled = False
btnColetar.Enabled = False
tnstring = Convert.ToString(trialnum)
While tnstring.Length < 3
tnstring = "0" & tnstring
End While
fname = pasta & "/" & nomearq & tnstring & ".emg" 'Modificado para usar variaveis locais
If File.Exists(fname) Then File.Delete(fname)
arq = New FileStream(fname, FileMode.Create) ' Arquivo da trial
Dim w As New StreamWriter(arq)
SerialPort1.DiscardInBuffer() 'Descarta os dados armazenados em buffer
SerialPort1.Write(New Byte() {&H1}, 0, 1) ' Comando para iniciar aquisição
' Varre o buffer de leitura em busca do MSB do primeiro canal (Bit7 = 1)
While sync < 128
sync = SerialPort1.ReadByte()
End While
frame(0) = sync ' MSB do primeiro canal no buffer
len = SerialPort1.Read(frame, 1, 15) ' Lê os outros 15 bytes do buffer para completar o frame
' Loop principal
For nframe = 1 To totalframes
For ch = 0 To 7
' Decodifica o valor do canal correspondente no frame
i = ch * 2
temp(ch) = frame(i + 1) ' Pega o LSB 0-127
If (frame(i) > 127 And ch > 0) Or (frame(i + 1) > 127) Or (frame(i) < 128 And ch = 0) Then
sincro = 1
sync = 0
While sync < 128
sync = SerialPort1.ReadByte()
End While
frame(0) = sync ' MSB do primeiro canal no buffer
For i = ch To 6
w.Write("1024" & ", ")
Next
w.WriteLine("1024")
Exit For
End If
frame(i) = frame(i) And 7 ' AND para zerar os 5 bits mais significativos
temp(ch) += 128 * (frame(i) Mod 2) ' Soma o bit 0 do MSB como bit 7 do LSB
frame(i) = frame(i) \ 2 ' Divisão inteira por 2, equivale a um right-shift de 1 bit
temp(ch) += 256 * frame(i) ' Soma o MSB na variável
If ch = 7 Then
w.WriteLine(temp(ch))
Else : w.Write(temp(ch) & ", ")
End If
temp(ch) -= 512 ' Subtrai metade da escala para ajustar o offset analógico
temp(ch) = Abs(temp(ch)) ' Valor absoluto (sem sinal)
Next
If nframe Mod 400 = 0 Then ' a cada 400 amostras = 0,2s
' Percorre os 8 canais atualizando os VUs pelo valor de cada canal
' 410 corresponde a 2V no conversor A/D
Lvl1.Value = temp(0)
If temp(0) > 410 Then Lvl1.ForeColor = Color.Red
Lvl1.Refresh()
Lvl2.Value = temp(1)
If temp(1) > 410 Then Lvl2.ForeColor = Color.Red
Lvl2.Refresh()
Lvl3.Value = temp(2)
If temp(2) > 410 Then Lvl3.ForeColor = Color.Red
Lvl3.Refresh()
Lvl4.Value = temp(3)
If temp(3) > 410 Then Lvl4.ForeColor = Color.Red
Lvl4.Refresh()
Lvl5.Value = temp(4)
If temp(4) > 410 Then Lvl5.ForeColor = Color.Red
Lvl5.Refresh()
Lvl6.Value = temp(5)
If temp(5) > 410 Then Lvl6.ForeColor = Color.Red
Lvl6.Refresh()
Lvl7.Value = temp(6)
If temp(6) > 410 Then Lvl7.ForeColor = Color.Red
Lvl7.Refresh()
Lvl8.Value = temp(7)
If temp(7) > 410 Then Lvl8.ForeColor = Color.Red
Lvl8.Refresh()
End If
If sincro = 0 Then
len = SerialPort1.Read(frame, 0, 16)
Else
len = SerialPort1.Read(frame, 1, 15)
sincro = 0
End If
Next
End Sub