Trouble with Serial.print/println.

Hey everyone.
I'm seriously about to go mad. I'm trying to use a hall effect sensor to measure the RPM of a fan, in specific time intervals (as 1, 2, 3 and 4 seconds), and control them via a Python interface (which I haven't even started yet, for I can get no output) All the functions work on their own. I mean, when I move say, "void scan" onto its own sketch and just run it without a serial command, it works fine. But when they're all together and being controlled by "SerialCommand", I get no goddamn "Serial.print" or "Serial.println"'s. When I give the command for "timer" functions, they work, the fan starts turning, but I get no serial output. When I use the scan function, the sketch just goes up to "Serial.println("I'm here") and dies afterwards. What could be the problem? I'm thinking the problem is with the "if (millis()" part. Am I missing something massive?

#include <SerialCommand.h>
#define pwmA 9
#define pwmB 10
SerialCommand sCmd;
const byte interruptPin = 2;
float rpm = 0;
unsigned long lastmillis = 0;
volatile int count = 0;
bool has_written = false;


void setup() {

  pinMode(interruptPin, INPUT_PULLUP);
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(interruptPin), flag, CHANGE);
  sCmd.addCommand("timerone", timerone);
  sCmd.addCommand("timertwo", timertwo);
  sCmd.addCommand("timerthree", timerthree);
  sCmd.addCommand("timerfour", timerfour);
  sCmd.addCommand("scan", scan);
  Serial.println("Ready");
}
void loop() {
  sCmd.readSerial();     // We don't do much, just process serial commands
}
void timerone() {
  analogWrite(pwmA, 255);
  analogWrite(pwmB, 0);
  if (millis() - lastmillis == 1000) {
    rpm = count * 60;
    Serial.println(rpm);
    count = 0;
    lastmillis = millis();
  }
}
void timertwo() {
  analogWrite(pwmA, 255);
  analogWrite(pwmB, 0);
  if (millis() - lastmillis == 2000) {
    rpm = count * 30;
    Serial.println(rpm);
    count = 0;
    lastmillis = millis();
  }
}
void timerthree() {
  analogWrite(pwmA, 255);
  analogWrite(pwmB, 0);
  if (millis() - lastmillis == 3000) {
    rpm = count * 20;
    Serial.println(rpm);
    count = 0;
    lastmillis = millis();
  }
}
void timerfour() {
  analogWrite(pwmA, 255);
  analogWrite(pwmB, 0);
  if (millis() - lastmillis == 4000) {
    rpm = count * 15;
    Serial.println(rpm);
    count = 0;
    lastmillis = millis();
  }
}
void scan() {
  Serial.println("initializing RPM count");
  int i = 0;
  while (i < 256)
  {
    if (!has_written) {
      analogWrite(pwmA, i);
      has_written = true;
      Serial.println("I'm here");
    }
    if (millis() - lastmillis == 1000) {
      Serial.println("I'm here 2");
      //detachInterrupt(digitalPinToInterrupt(interruptPin));
      rpm = count * (60);
      Serial.print(rpm);
      Serial.print(" ");
      Serial.println(i);
      count = 0;
      lastmillis = millis();
      i++;
      has_written = false;
      attachInterrupt(digitalPinToInterrupt(interruptPin), flag, CHANGE);
    }
  }
}
void flag() {
  count++;
}

I'm not familiar with that library but I'm guessing that typing "timerone" into the Serial monitor will cause the associated function to be executed ONCE? So at that time, how many milliseconds have passed since the previous command updated lastMillis? I bet a thousand to one that it wasn't an even number of thousand milliseconds ago.

This will never, ever work in a predictable fashion:

if (millis() - lastmillis == 1000) {
...
if (millis() - lastmillis == 2000) {
...
if (millis() - lastmillis == 3000) {
...
if (millis() - lastmillis == 4000) {

What you need to do is:

if (millis() - lastmillis >= 1000) {
...
if (millis() - lastmillis >= 2000) {
...
if (millis() - lastmillis >= 3000) {
...
if (millis() - lastmillis >= 4000) {

There may be other problems, especially with the usage of attachInterrupt() function, but those millis() logic errors jump off the page.

Thank you guys for replying! Yeah, changing lastmillis == 1000 to lastmillis>=1000 makes sense! MorganS' running once part makes sense too but I have no idea how to solve that. I've even checked the Timer libraries but can't for the life of me figure something out.

Google “state machine”. It doesn’t have to be complicated, you just need to keep track of which mode the program is in and call the corresponding routine in loop() so that it repeats.

Youll probably also want a method to exit out of the four possible time periods to an idle, or do nothing loop, same as when the program begins.

metalli-guy:
Thank you guys for replying! Yeah, changing lastmillis == 1000 to lastmillis>=1000 makes sense! MorganS' running once part makes sense too but I have no idea how to solve that. I've even checked the Timer libraries but can't for the life of me figure something out.

The Timer libraries is the wrong rabbit hole.

The loop() should be checking the timer and deciding if it's time to do a calculation or print something. The functions/commands that you've specified could probably just change the value of a variable to the duration you want. Make a new global variable and give it a name that makes sense to you. printInterval makes sense to me. Initialise it to some value like 1000 or 0 and let the commands change it. Your loop might interpret 0 as the "never print" state.

MorganS:
The Timer libraries is the wrong rabbit hole.

The loop() should be checking the timer and deciding if it's time to do a calculation or print something. The functions/commands that you've specified could probably just change the value of a variable to the duration you want. Make a new global variable and give it a name that makes sense to you. printInterval makes sense to me. Initialise it to some value like 1000 or 0 and let the commands change it. Your loop might interpret 0 as the "never print" state.

I think your last statement hit the point exactly. I solved the problem by the way, I only needed to add a return scan() line at the end so it "fakes" a loop, I think. I get outputs now, though I have no idea how.