Shop OBEX P1 Docs P2 Docs Learn Events
It doesn't println? — Parallax Forums

It doesn't println?

PlaneTeeRPlaneTeeR Posts: 100
edited 2006-06-16 10:55 in General Discussion
Hey the main application uses the processor which uses the sensor, for formatting it uses DisplayFormat. I made objects of these and want to display a simple println but it doesn't print to the jide message window. What is wrong here?

Thanks Johnny
«1

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-02 14:29
    Classes are looking much better now.
    Change the method formatSpeed to
    · public StringBuffer formatSpeed(int x){
    ··· a=0;
    ··· a = Format.bprintf(textSpeed,a,"%0d.",x/10);
    ··· a = Format.bprintf(textSpeed,a,"%d",x%10);
    ··· textSpeed[noparse][[/noparse]a]=0;
    ··· Format.printf("debug: %s\n",textSpeed); //debug textSpeed
    ··· b=0;
    ··· while (textSpeed[noparse][[/noparse]b]!=0){
    ····· string.append(textSpeed[noparse][[/noparse]b]);
    ····· b++;
    ··· }
    ··· return string;
    · }

    and see if the debug does get printed, it should.

    Why do you keep converting asciiz strings to StringBuffer and then to String?
    The Format class can print asciiz strings directly. No need for all these
    conversions.

    In the jide message window, make sure the enable option is on!

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-02 14:49
    Your main() is missing a while true loop.
    It should be

    · public static void main() {
    ··· proc = new Processor(15);
    ··· t = new Timer();
    ··· df = new DisplayFormat();
    ··· while (true) {
    ····· proc.calculateSpeed();
    ····· t.mark();
    ····· if (t.timeoutSec(3)){
    ······· b = true;
    ····· }
    ····· while (b == true){
    ······· a1 = df.formatSpeed(proc.getSpeed());
    ······· a2 = a1.toString();
    ······· System.out.println(a2);
    ······· b=false;
    ····· }
    ··· }
    · }

    otherwise b=false and main() ends.

    You can simplify main to

    · public static void main() {
    ··· proc = new Processor(15);
    ··· t = new Timer();
    ··· df = new DisplayFormat();
    ··· while (true) {
    ····· proc.calculateSpeed();
    ····· a1 = df.formatSpeed(proc.getSpeed());
    ····· a2 = a1.toString();
    ····· System.out.println(a2);
    ····· t.mark();
    ····· while·(!t.timeoutSec(3)) ; //wait for 3 sec
    ··· }
    · }



    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-02 15:58
    Hey peter, just added the line to the programming but didn't print anything! Hmm this is very strange, does it print on your javelin?

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-02 16:03
    I have no javelin connected right now.
    Are you sure the jide message window Enabled is on?
    If it is not, nothing gets printed to the jide message window.
    Add a welcome message to the start of main.
    Format.printf("ApplicationFCv1\n");
    Does that get printed?

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-02 16:14
    I spotted the error.
    You define a new processor in main().
    The processor constructor defines a new sensor.
    The sensor constructor calls run().
    run() contains a while true loop that never exits.
    So, code execution never continues back to main().

    You should make the innerloop of that while true loop
    a seperate method.
    Then call that method from your main while true loop.
    (The sensor constructor then must not call run())

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-02 16:43
    Hmm oke from which main while true loop mus i call the method? I don't get that part? can you show me?

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-02 18:16
    I moved your declarations for used resources and main objects
    to your application class.
    The required objects for classes are passed via constructors.

    Note how your mainloop now shows exactly your program flow.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-02 18:48
    Ah i see, yes i also thought about making objects of sensor and processor in application, but didn't know how exactly to do it. I see what you mean now, this works fine! I comprehend this code completely know.

    Thanks for your help peter!

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-02 19:02
    Now that you understand how to use objects properly,
    take a look at your DisplayFormat class. In my opinion
    the Processor needs not to be known to the display class.
    Instead of calling a Processor method from
    the display class, pass the values to print via the
    methods formatAverage and formatDistance,
    just as you did with formatSpeed.
    Then you don't need to pass the Processor object to the display
    class.

    regards peter
    ·
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-02 19:57
    Coming back on the code, tested it. Got much IDE error's. I have a question, why can't the sensor not have loop forever for pulses and the application do things at the same time. Isn't that called multitasking?

    Johnny

    P.S. i will get back on the other classes later
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-02 20:21
    The javelin is not a real multitasking device. It only provides
    background tasks (the VP's). No threads. So, to mimic
    multitasking you should implement state machines for
    several tasks.
    A state machine maintains its state, and is frequently called
    from the mainloop. Specific·events (for example a pin input state change)
    change the state machine its state. The trick is never to wait for any
    event to happen, rather introduce a wait·state from which is
    immediately returned if the event has not happened.

    int state;
    int timePassed;

    public boolean getPulse() {
    · switch (state) {
    ··· case 0: //wait for senPin to be high
    ·············· if (CPU.readPin(senPin)) state++;
    ·············· return false;
    ··· case 1: //wait for senPin to be low
    ·············· if (!CPU.readPin(senPin)) {
    ················ t.mark();
    ················ state++;
    ···············}
    ·············· return false;
    ··· case 2: //wait for senPin to be high, then store pulse width
    ·············· if (CPU.readPin(senPin)) {
    ················ timePassed = t.passedMS();
    ················ state=0;
    ·················return true;
    ···············}
    ·············· return false;
    ··· default: state=0;
    ·············· return false;
    · }
    }


    The idea is to call getPulse() from the mainloop and when it returns true,
    you retrieve the·last timePassed, from which you can calculate speed.
    As you can see, the·state machine equals the code you had for reading a pulse,
    but it is split into small fragments called states. Note that the code never
    waits. This allows you to execute other code from the mainloop while
    no event has happened.

    regards peter


    Post Edited (Peter Verkaik) : 6/2/2006 8:26:59 PM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-03 10:31
    I created an ApplicationFCv2 that implements the statemachine approach.
    All·files in package fietsv2
    Note that Processor class is no longer needed.
    The calculateDistance and calculateAverage are now in the application class.
    The Clock class maintains the realtime clock.

    regards peter


    Post Edited (Peter Verkaik) : 6/3/2006 12:13:43 PM GMT
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-04 11:38
    Peter,

    I've run a quick test on on my javelin stamp with this code.

    When the magnet runs by the hall sensor it somethimes leaves the LED burning till the magnet comes again.

    Also it can not keep up at higher speeds.

    Also after few pulses it generates an Out of bounds exception.

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-04 12:37
    I figured that would be a possible effect using the statemachine approach.
    The problem is the sensor signal has a small high period and a large low period.
    I adapted the sensor update() method to wait for the high period, and while it is high,
    the update() does not return to the mainloop. Since the high period is small, this
    should have no impact on the program behaviour, but does allow to detect
    the start of the low period.

    Please post the results using this adaptation.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-04 16:22
    It got worse, the LED starts to burn when the program starts, and the sensor readings are worse. When a pulse·come by the·LED goes off, pulse comes by LED goes on. And so on..

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-04 16:50
    That is correct. See the update() in Sensor.java
    The led toggles with every pulse detected. I think that·is more clear
    than having the led on only when the sensor signal is high due to
    the small time the sensor signal is high. With toggling, at constant speed the led
    on time and off time are equal (at least it is supposed to be, if it isn't
    it indicates pulses are missed).

    Another thing, your calculateDistance() method uses the pulsecount to
    calculate distance. That method uses the calculation
    ····· dstm = UnsignedIntMath.umulf(circumference,1500);
    The umulf() calculates circumference * (1500/65536), and since
    circumference = 2 that always results in 0.
    The right calculation for distance using pulses is
    · distance += circumference * pulsecount
    where circumference = 20 (20 equals twenty 0.1m units or 2.0m)
    For every pulse, add 20 to the distance.
    That only works if no pulses are missed.

    Could you post the ide message window output you get?

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-04 17:18
    output:
    ApplicationFCv2
    Sp = 000.00 km/h
    D1 = 0.00 km
    D2 = 0.00 km
    Sp = 008.19 km/h
    D1 = 0.00 km
    D2 = 0.01 km
    Sp = 009.76 km/h
    D1 = 0.00 km
    D2 = 0.01 km
    Sp = 007.09 km/h
    D1 = 0.00 km
    D2 = 0.02 km
    Sp = 008.44 km/h
    D1 = 0.00 km
    D2 = 0.03 km
    Sp = 009.09 km/h
    D1 = 0.00 km
    D2 = 0.03 km
    Sp = 015.41 km/h
    D1 = 0.00 km
    D2 = 0.04 km
    Sp = 014.57 km/h
    D1 = 0.00 km
    D2 = 0.05 km
    Sp = 024.08 km/h
    D1 = 0.00 km
    D2 = 0.07 km
    Sp = 020.81 km/h
    D1 = 0.00 km
    D2 = 0.09 km
    Sp = 020.81 km/h
    D1 = 0.00 km
    D2 = 0.10 km
    Sp = 024.16 km/h
    D1 = 0.00 km
    D2 = 0.12 km
    Sp = 031.72 km/h
    D1 = 0.00 km
    D2 = 0.14 km
    Sp = 061.53 km/h
    D1 = 0.00 km
    D2 = 0.18 km
    Sp = 053.33 km/h
    D1 = 0.00 km
    D2 = 0.21 km
    Sp = 015.75 km/h
    D1 = 0.00 km
    D2 = 0.24 km
    Sp = 007.94 km/h
    D1 = 0.00 km
    D2 = 0.25 km
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-04 22:31
    I have put a sensor timing diagram in sensor.java
    From this diagram it is clear the minimal pulsetime for
    the sensor is 20 msec.
    I added a poll() method in Sensor.java that returns the current speed.

    Could you post the ide message window output for this adaptation?

    regards peter

    Post Edited (Peter Verkaik) : 6/5/2006 12:50:53 AM GMT
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-06 10:57
    Dear peter,

    The clock of the bike is not an actual clock but gives the time that the bike was cycling. (rittijd)
    How can i implement that in this way? Because my way doesn't seem to work (the passed time adding, you know what i did)

    Thanks Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-06 12:38
    Johnny,
    The realtime clock always starts at 0, and so it is your traveltime.
    There are two ways to keep the time:
    1. to add the passed time between pulses
    2. to add time in small chunks using a timer loop
    The 2nd makes the timekeeping independant from your· sensor pulses
    and does take into account the time used by other code.
    The clock class uses the 2nd approach.
    Note that the clock timer is only marked just before the mainloop.
    It is easy to·add a startstop button to stop/start the clock
    (making it a stopwatch), so it would only count while cycling.
    This startstop button could be virtual: stop the clock if no pulses
    are received (eg. the bike stopped), start the clock when
    pulses are received.
    I added a startstop() and reset() to the clock class.
    The clock initalizes to stop. So startstop() must be called at
    the start of main.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-06 13:58
    The start must begin with the first pulse not at the beginning of the main because the bike computer will not count until you cycle. But this will mean that the main must be programmed different than just adding startstop?

    Because it is now a state machine must the start and stop of the clock not be controlled from the sensor because there are the state?

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-06 14:42
    The mainloop controls the clock by checking wether the bike moves
    (speed > 0) or is stopped (speed =0).
    I added a seperate start() and stop() to make it easier.

    Note that poll() in Sensor is not a statemachine but poll() waits
    for two consecutive high pulses, the time between those 2 high pulses
    determines the speed. (speed=circumference/time)

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-07 17:31
    Hey peter,

    Thanks for the help. It works fine now. I can work further on putting this al together with the lcd codes andso on.

    If i also want to add class button to it, to input circumference and switch between display? where must i begin with that?

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-07 18:21
    You can simply test for a low input pin
    to change mode:
    · if (!CPU.readPin(modePin)) {
    ··· mode = (mode+1)%3; //support for 3 modes
    · }

    For wheel circumference you best have a number of standard
    wheel circumferences (26" and 28" are two standard values)
    Then you can use
    · if (!CPU.readPin(parameterPin)) {
    ··· circumferenceIndex = (circumferenceIndex+1)%2; //support for 2 wheel sizes
    ··· circumference = circumferenceArray[noparse][[/noparse]circumferenceIndex];
    ··· sen.setCircumference(circumference);
    · }
    static final·int[noparse]/noparse circumferenceArray = {20,24};

    Put the 2 button test simply before clock update in mainloop.
    The remaining code·takes enough time so debouncing is not required.
    You must add a method setCircumference to the Sensor class.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-08 19:01
    Dear Peter,

    I've tried the following code that I created to initialise the circumference.

    while (true) {
    if (!CPU.readPin(bt1Pin)){
    circumferenceIndex = (circumferenceIndex+1)%9; //support for 9 wheel sizes
    circumference = circumferenceArray[noparse][[/noparse]circumferenceIndex];
    }
    if (!CPU.readPin(bt2Pin)){
    break;
    }
    }

    This is the result: I push button 2 the program starts, I push button 1 and also the program starts and the buttons are not on the same pin I checked that.

    Thanks Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-08 20:16
    You have put a pullup resistor on each pin?
    A value of 10k or 4k7 will do.
    Without the resistors there may be noise
    at pin2 which leads to starting the program.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-08 20:26
    I have put normal resistors on each pin 10k Ohm and i have a normal pushbutton.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-08 20:57
    Then try:

    while (true) {
    · if (!CPU.readPin(bt1Pin)){
    ··· circumferenceIndex = (circumferenceIndex+1)%9; //support for 9 wheel sizes
    ··· circumference = circumferenceArray[noparse][[/noparse]circumferenceIndex];
    ··· System.out.println(circumference);
    ··· if (!CPU.readPin(bt2Pin)) {
    ····· System.out.println("pin2 is low");
    ··· }
    ··· CPU.delay(10500); //wait 1 second
    · }
    · if (!CPU.readPin(bt2Pin)){
    ··· break;
    · }
    }

    While you keep bt1pin pressed, you should see a new circumference displayed every second.
    If you never press bt2pin, the while loop should never exit. If you press bt1pin, the status
    of bt2pin is displayed if it is also low, which shouldn't be. If it is there is some
    wiring problem.


    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-06-09 13:34
    this has no effect still doing the same thing! I can't figure out what the problem is, It's not the wiring I think. I didn't even show the system.out.println.

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-06-09 14:09
    Post your main class.
    regards peter
Sign In or Register to comment.