Go Down

Topic: Serial.print() giving odd behaviour (Read 992 times) previous topic - next topic

Dohrann

I am currently working on a project controlling MIDI inputs/outputs using an Arduino Uno.  I am getting some odd outputs and have narrowed down my problem to be within Serial.print() and/or Serial.println() (have tried both).  Current Code:

Code: [Select]

#include <MIDI.h>
#define LED1 7
#define LED2 6

void setup() {
  MIDI.begin(MIDI_CHANNEL_OMNI);        //Listen to all channles (note, cannot send data)
  Serial.begin(31250);                  //31250 - standard MIDI baud rate
  Serial.print("MIDI input test -- 03/20/13 --\n--Display Note, channel(1 or 16), note, velocity\n");
  pinMode(LED1,OUTPUT);
  pinMode(LED2,OUTPUT);
  BoardOn(3);
}

void BoardOn(byte num) { // Set an initation blink and an 'On' LED
  for (byte i=0;i<num;i++) {
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,HIGH);
    delay(30);
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,LOW);
    delay(30);
  }
  digitalWrite(LED1,HIGH);
  digitalWrite(LED2,HIGH);
}

unsigned long t=0;                      //time in milliseconds

void loop() {
  int type;        //type of messege, note, velocty, channel, data 1, data 2
  byte note, v, ch, d1, d2;
  if( MIDI.read() ) {                   //If messege incoming
    byte type = MIDI.getType();
 
    switch( type ) {
      case NoteOn:
        note = MIDI.getData1();
        v = MIDI.getData2();
        ch = MIDI.getChannel();
        if (v > 0){
          Serial.print(String("Note on: ch=") + ch + ", note=" + note + ", velocity=" + v + "\n");     
        } else {
          Serial.print(String("Note off: ch=") + ch + ",note=" + note + "\n");
        }
        break; 
      case NoteOff:
        note = MIDI.getData1();
        v = MIDI.getData2();
        ch = MIDI.getChannel();
        Serial.print(String("Note off: ch=") + ch + ", note=" + note + ", velocity=" + v + "\n");
        break;
      default:
        //d1 = MIDI.getData1();
        //d2 = MIDI.getData2();
        //Serial.println(String("Messege, type=") + type + ", data = " + d1 + " " + d2);
        break;
    }
    t=millis();
  }
  if( (millis() - t) > 10000 ) {
    t += 10000;
    Serial.print("Inactive for 10seconds or more.\n");
  }
}


This prints out everytime I press down or let up a note (using an electronic keyboard).  I get outputs that are correct, although the issue is my output adding random characters to the begging of every new line. 
Example Output:
Code: [Select]

MIDI input test -- 03/20/13 --

--Display Note, channel(1 or 16), note, velocity

4PNote on: ch=1, note=52, velocity=800

4 Note off: ch=1,note=520

5PNote on: ch=1, note=53, velocity=800

5 Note off: ch=1,note=530

+PNote on: ch=1, note=43, velocity=800

+ Note off: ch=1,note=430

HPNote on: ch=1, note=72, velocity=800

H Note off: ch=1,note=720


The odd thing is the 'random' characters are consistent with the note I press, as you can see, every On has a corresponding Off with the same leading character.  I have narrowed down my error search to the Serial.print() function.  I have replaced everything within the print() to something consistent, and it still does the same thing.

IMPORTANT:
As you may know, Arduino does not support MIDI baud rate of 31250 in the serial monitor, I am montering my COM port using pySerial and a small Python program.

test.py
Code: [Select]

#!/usr/bin/env python3.3
#encoding: utf-8

import sys
import re
import serial

def main():
    ser = serial.Serial('COM9',31250)              #enable for non-command line argument version
    ser.timeout = 10                                  #Set timeout so readline() cannot block forever
    ser.setRTS(True)
    ser.setRTS(False)
    ser.close()                                     #be safe, close the port before opening (rids Windows errors...)
    ser.open()                                      #Open the port between arduino serial and python

    while 1:
        d1 = ser.readline();                        #d1 will be a BYTE class
        data = d1.decode('utf-8','ignore')                   #convert BYTE class into str
        print(data)

    ser.close()


I do not believe the .decode is the problem as if I only print the readline() result, I get the encoded data, along with the 'random' character and then my Arduino print statement. 

I tried to provide as much info as possible, if anyone has heard of a problem with Serial.print() or sees some newb mistake I am making, I would greatly appreciate the help :)

Thanks once again

marco_c

Is the MIDI and the Serial prnting one the same serial port?
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

Dohrann


Is the MIDI and the Serial prnting one the same serial port?

Only the Arduino is printing to the serial port. The Python script is only reading from said serial port.

marco_c

Maybe so, but the Arduino IDE must be getting the data to dsplay from somewhere any you only have one serial port open ..

Thge MIDi library is writing it's stuff to the serial port, same as Serial.print. What COM port is the Python script reading from and is this the same as the IDE?

It is far, far, far more likely that you have some error in the COM port config than there being a problem in the Serial.print library.
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

Dohrann


Maybe so, but the Arduino IDE must be getting the data to dsplay from somewhere any you only have one serial port open ..

Thge MIDi library is writing it's stuff to the serial port, same as Serial.print. What COM port is the Python script reading from and is this the same as the IDE?

It is far, far, far more likely that you have some error in the COM port config than there being a problem in the Serial.print library.


Python script is reading from COM9 and the Arduino IDE is set on COM9 as well.  I don't get an error on my Python when opening the connection and according to http://playground.arduino.cc/interfacing/python I am reading correctly.

This leaves me still wondering what is prepending characters to my print.

marco_c

Think about what you have just written. The same com port has the midi and debug messages coming to it. What do you think the serial console is going to display?

Easy check. - don't send the midi message and see if your "print" problem disappears.
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

PaulS

Code: [Select]
          Serial.print(String("Note on: ch=") + ch + ", note=" + note + ", velocity=" + v + "\n");     
This is just plain wrong. Wasting precious resources so you can have just one Serial.print() statement is plain laziness. Do it right.

Dohrann

#7
Apr 20, 2013, 09:46 pm Last Edit: Apr 20, 2013, 10:14 pm by Dohrann Reason: 1

Code: [Select]
          Serial.print(String("Note on: ch=") + ch + ", note=" + note + ", velocity=" + v + "\n");     
This is just plain wrong. Wasting precious resources so you can have just one Serial.print() statement is plain laziness. Do it right.


I'm sorry, could you elaborate, I am unsure what you mean.


Think about what you have just written. The same com port has the midi and debug messages coming to it. What do you think the serial console is going to display?

Easy check. - don't send the midi message and see if your "print" problem disappears.

I found the cause of my problems.  I use MIDI.begin() AND Serial.begin(31250).  Both are not needed, when I comment out MIDI.begin(), everything runs perfectly.  Although, if I comment out Serial.begin(31250) and leave MIDI.begin() things go wrong again, any idea what may be causing MIDI.begin() to act weird on the serial connection?

marco_c

Nothing is acting 'weird'. If you share the same serial connection you will see messages from everything that uses that connection. As I have already said several times, you cannot mix MIDI and serial debug on the same serial line and expect it the output to be 'clean'.

If you are just using this for debugging, then live with it and move on. Once you remove the debug statements all that will be left if the midi. If you mean to use this for information, then you need to find a different solution for the messages (LCD 4 line display, for example) that is separate.
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

PaulS

Quote
I'm sorry, could you elaborate, I am unsure what you mean.

Sure.

Code: [Select]
Serial.print(String("Note on: ch=") + ch + ", note=" + note + ", velocity=" + v + "\n");
There is a call to the String constructor, to hold the string "Note on: ch=". Then there are 6 calls to the copy constructor to concatenate each of the other parts. When, Serial.print() prints the string that String wrapped. Finally, there are 7 calls to the String destructor. All so you can have one call to Serial.print().

Code: [Select]
Serial.print("Note on: ch=");
Serial.print(ch);
Serial.print(", note=");
Serial.print(note);
Serial.print(", velocity=");
Serial.println(v);

involves no constructors, no destructors, and no memory fragmentation. But it does involve a little more typing. Once.

Dohrann


Nothing is acting 'weird'. If you share the same serial connection you will see messages from everything that uses that connection. As I have already said several times, you cannot mix MIDI and serial debug on the same serial line and expect it the output to be 'clean'.

If you are just using this for debugging, then live with it and move on. Once you remove the debug statements all that will be left if the midi. If you mean to use this for information, then you need to find a different solution for the messages (LCD 4 line display, for example) that is separate.


Updated last post as I found my root cause.


Quote
I'm sorry, could you elaborate, I am unsure what you mean.

Sure.

Code: [Select]
Serial.print(String("Note on: ch=") + ch + ", note=" + note + ", velocity=" + v + "\n");
There is a call to the String constructor, to hold the string "Note on: ch=". Then there are 6 calls to the copy constructor to concatenate each of the other parts. When, Serial.print() prints the string that String wrapped. Finally, there are 7 calls to the String destructor. All so you can have one call to Serial.print().

Code: [Select]
Serial.print("Note on: ch=");
Serial.print(ch);
Serial.print(", note=");
Serial.print(note);
Serial.print(", velocity=");
Serial.println(v);

involves no constructors, no destructors, and no memory fragmentation. But it does involve a little more typing. Once.

Thank you that made much more sense, I changed my code accordingly and tested some timing, it does run much faster thank you. :D

Go Up