Looks like now < hearbeatTimer may never be true. heartbeatTimer is initialized to millis() which guarantees the first first call here will have now > heartbeatTimer. Then hearbeatTimer is only ever set to now when now is greater than hearbeatTimer.